Quick Guide To Geomorph v2.1
Quick Guide To Geomorph v2.1
Table
of
Contents
Table
of
Contents
......................................................................................................................................
2
Introduction
..............................................................................................................................................
4
I.
What
is
geomorph?
....................................................................................................................................................................
4
II.
How
to
use
this
manual
.........................................................................................................................................................
4
III.
Installing
geomorph
and
R
.................................................................................................................................................
7
IV.
Workflows
for
common
analyses
....................................................................................................................................
9
V.
Example
datasets
in
geomorph
........................................................................................................................................
10
VI.
Permutation
tests
................................................................................................................................................................
11
VII.
Statistical
Designs
..............................................................................................................................................................
11
Section
2:
Data
Input:
Importing
landmark
data
......................................................................................
13
1.1
TPS
files
(readland.tps)
....................................................................................................................................................
13
1.2
NTS
files
(readland.nts)
...................................................................................................................................................
14
1.3
Multiple
NTS
files
of
single
specimens
(readmulti.nts)
.....................................................................................
15
1.4
Morphologika
files
(read.morphologika)
.................................................................................................................
16
1.5
Other
text
files
......................................................................................................................................................................
17
Section
2:
Data
Preparation:
Manipulating
landmark
data
and
classifiers
................................................
19
2.1
Data
object
formats
............................................................................................................................................................
19
3D
array
(p
x
k
x
n)
.........................................................................................................................................................................
19
2D
array
(n
x
[p
x
k])
......................................................................................................................................................................
19
2.2
Converting
a
2D
array
into
a
3D
array
(arrayspecs)
...........................................................................................
19
2.3
Converting
a
3D
array
into
a
2D
array
(two.d.array)
..........................................................................................
20
2.4
Making
a
factor:
group
variables
.................................................................................................................................
20
2.5
Lists
...........................................................................................................................................................................................
21
2.6
Estimating
missing
landmarks
(estimate.missing)
..............................................................................................
22
2.7
Rotate
a
subset
of
2D
landmarks
to
common
articulation
angle
(fixed.angle)
........................................
24
Section
3a:
Generalized
Procrustes
Analysis
............................................................................................
25
3.1
Generalized
Procrustes
Analysis
(gpagen)
..............................................................................................................
25
3.2
Generalized
Procrustes
Analysis
with
Bilateral
Symmetry
Analysis
(bilat.symmetry)
.......................
29
Section
3b:
Data
Analysis
.........................................................................................................................
32
3.3
Covariation
methods:
Procrustes
ANOVA/regression
for
shape
data
(procD.lm)
.................................
33
3.4
Covariation
methods:
Procrustes
ANOVA
and
pairwise
tests
for
shape
data,
using
complex
linear
models
(advanced.procD.lm)
....................................................................................................................................................
35
3.5
Covariation
methods:
Two-‐block
partial
least
squares
analysis
for
shape
data
(two.b.pls)
.............
40
3.6
Morphological
Integration
methods:
Quantify
morphological
integration
between
two
modules
(morphol.integr)
............................................................................................................................................................................
41
3.7
Morphological
Integration
methods:
Compare
modular
signal
to
alternative
landmark
subsets
(compare.modular.partitions)
.................................................................................................................................................
43
define.modules
..................................................................................................................................................................................
46
3.8
Phylogenetic
Comparative
methods:
Assessing
phylogenetic
signal
in
morphometric
data
(physignal)
........................................................................................................................................................................................
47
3.9
Phylogenetic
Comparative
methods:
Quantify
phylogenetic
morphological
integration
between
two
sets
of
variables
(phylo.pls)
.............................................................................................................................................
49
3.10
Phylogenetic
Comparative
methods:
Comparing
rates
of
shape
evolution
on
phylogenies
(compare.evol.rates)
....................................................................................................................................................................
50
2
3.11
Phylogenetic
Comparative
methods:
Phylogenetic
ANOVA/regression
for
shape
data
(procD.pgls)
......................................................................................................................................................................................
51
3.12
Calculate
morphological
disparity
for
one
or
more
groups
(morphol.disparity)
................................
52
3.13
Quantify
and
compare
shape
change
trajectories
(trajectory.analysis)
..................................................
53
Section
4:
Visualization
............................................................................................................................
57
4.1
Principal
Components
Analysis
(plotTangentSpace)
..........................................................................................
57
mshape
.................................................................................................................................................................................................
60
4.2
Find
potential
outliers
(plotOutliers)
........................................................................................................................
61
4.3
Plot
allometric
patterns
in
landmark
data
(plotAllometry)
.............................................................................
62
4.4
Plot
phylogenetic
tree
and
specimens
in
tangent
space
(plotGMPhyloMorphoSpace)
.......................
65
4.5
Create
a
mesh3d
object
warped
to
the
mean
shape
(warpRefMesh)
..........................................................
66
findMeanSpec
....................................................................................................................................................................................
68
4.6
Create
an
outline
object
warped
to
the
mean
shape
(warpRefOutline)
.....................................................
68
4.7
Plot
landmark
coordinates
for
all
specimens
(plotAllSpecimens)
................................................................
70
4.8
Plot
shape
differences
between
a
reference
and
target
specimen
(plotRefToTarget)
.........................
72
define.links
..........................................................................................................................................................................................
79
gridPar
.................................................................................................................................................................................................
80
4.9
Plot
3D
specimen,
fixed
landmarks
and
surface
semilandmarks
(plotspec)
............................................
82
Section
5:
Data
Collection
(Digitizing)
......................................................................................................
83
5.1
2D
data
collection
(digitize2d)
.....................................................................................................................................
83
5.2
Define
sliding
semilandmarks
(define.sliders)
......................................................................................................
85
5.3
Importing
3D
surface
files
(read.ply)
.........................................................................................................................
88
5.4
3D
data
collection:
landmarks
(digit.fixed)
.............................................................................................................
89
5.5
3D
data
collection:
landmarks
and
semilandmarks
............................................................................................
91
buildtemplate
....................................................................................................................................................................................
91
editTemplate
.....................................................................................................................................................................................
94
digitsurface
........................................................................................................................................................................................
95
5.6
Calculate
semilandmarks
along
a
curve
(digit.curves)
......................................................................................
97
Frequently
Asked
Questions
....................................................................................................................
99
References
............................................................................................................................................
100
3
Introduction
I. What
is
geomorph?
Geomorph
is
a
freely
available
software
package
for
geometric
morphometric
analyses
of
two-‐
and
three-‐dimensional
landmark
(shape)
data
in
the
R
statistical
computing
environment.
It
can
be
installed
from
the
Comprehensive
R
Archive
Network,
CRAN
http://cran.r-‐
project.org/web/packages/geomorph/.
Occasionally,
we
make
updates
between
uploads
to
CRAN.
Users
can
install
via
tarball
the
current
beta
version
from
http://people.wku.edu/michael.collyer/geomorph/update.htm.
How
to
cite:
When
using
geomorph
in
publications,
please
cite
the
software
with
version
and
the
publication.
Type
in
R
console
> citation(package="geomorph")
Adams,
D.C.,
and
E.
Otarola-‐Castillo.
2013.
geomorph:
an
R
package
for
the
collection
and
analysis
of
geometric
morphometric
shape
data.
Methods
in
Ecology
and
Evolution.
4:393-‐399.
Adams,
D.C.,
M.
L.
Collyer,
and
E.
Sherratt.
2015
geomorph:
Software
for
geometric
morphometric
analyses.
R
package
version
2.1.x
http://cran.r-‐project.org/web/
packages/geomorph/index.html.
Figure
1
Overview
of
the
morphometric
analysis
process.
In
blue
are
the
steps
performed
in
R
and
geomorph,
and
those
in
orange
are
done
outside
of
R
and
imported
in.
4
In
section
1,
we
go
over
how
to
import
data
files
of
(raw)
landmark
coordinates
digitized
elsewhere,
e.g.,
using
software
such
as
ImageJ
or
tpsDig
for
2D
data,
or
IDAV
Landmark
editor,
AMIRA,
Microscribe
for
3D
data
(note
that
data
collection
–
digitizing
landmarks
–
can
also
be
done
in
geomorph,
and
is
outlined
in
section
5).
In
section
2,
we
demonstrate
some
techniques
and
functions
for
preparing
and
manipulating
imported
datasets,
such
as
adding
grouping
variables
and
estimating
missing
data,
and
adjusting
articulated
datasets
(2D
only).
Note
that
some
functions
described
in
this
section
can
also
be
used
on
Procrustes
coordinate
data,
but
are
presented
here
because
they
are
important
steps
to
learn
familiarize
the
user
with
the
R
environment.
In
section
3a,
the
raw
data
are
taken
through
the
morphometric-‐specific
step
of
alignment
using
a
generalized
Procrustes
superimposition,
which
is
imperative
for
raw
coordinate
data.
In
section
3b,
the
statistical
analysis
functions
are
presented
in
order
by
type
of
analysis
(Table
1).
In
section
4,
we
describe
how
to
plot
and
visualize
the
data
analysis
results,
including
shape
deformation
graphs
and
ordination
plots
(e.g.,
PCA).
Table
1
Functions
in
geomorph
~~**~~
Finally,
I
occasionally
write
source
code
for
very
specific
issues
to
complement
geomorph
functions.
They
can
be
found
here:
http://emsherratt.github.io/MorphometricSupportCode/
6
III. Installing
geomorph
and
R
These
instructions
assume
you
already
have
R
(and
perhaps
also
RStudio)
installed.*1
To
install
the
geomorph
package:
type
into
the
console:
install.packages("geomorph")
(Note
the
dependencies
of
geomorph
are:
rgl,
jpeg,
ape,
geiger,
phytools,
and
these
should
be
installed
also.)
Alternatively:
Rapp:
Packages
&
Data
>
Package
Installer
>
Choose
CRAN
(binaries)
from
dropdown
menu,
type
geomorph
in
box
and
click
get
list.
Select
geomorph,
select
install
dependancies
box,
and
click
install
selected.
or
Rstudio:
Packages
tab
>
Install:
Install
from
CRAN
repository
>
type
geomorph
in
box
and
select
install
dependancies
box,
and
click
install.
CRAN
restricts
the
number
of
updates
package
maintainers
can
make
in
a
year.
Therefore
we
have
a
beta
version
with
the
most
current
updates
and
bug
fixes,
which
has
yet
to
be
submitted
to
CRAN
for
diagnostic
checks.
It
is
held
on
a
GitHub
repository
available
here.
To
install
the
beta
geomorph
package:
install.packages("devtools")
devtools::install_github("EmSherratt/geomorph",ref = "Develop")
To
install
the
geomorph
package
from
Package
source:
Downloaded
from
CRAN
the
Package
Source
(.tar.gz
file,
aka
tarball).
Type
and
replace
path
with
the
path
to
file
in
"":
install.packages(path, repos = NULL, type = "source")
Rapp:
Packages
&
Data
>
Package
Installer
>
Choose
Local
Source
Package
from
dropdown
menu,
click
install,
and
browse
directory
for
.tar.gz
file
then
click
open.
Rstudio:
Packages
tab
>
Install:
Install
from
Package
Archive
File
>
browse
directory
for
.tar.gz
file
and
click
install.
To
install
the
beta
or
a
package
from
source,
you
will
need
to
have
GCC
and
Fortran
compilers
installed
on
your
computer
(details
on
next
page).
1
Installing
R
on
your
computer:
1) Download
the
R
installer
from
CRAN.
Double-‐click
on
the
installer
to
install
R
as
you
would
any
software.
For
Windows
users
on
a
network
computer,
install
R
into
your
Documents
directory
(or
any
folder
you
have
permission
to
access),
NOT
into
the
program
files
directory
(this
avoids
permission
issues).
2) Download
RStudio
if
you
so
wish
-‐
many
users
find
RStudio
to
be
a
more
user
friendly
interface
than
the
Rapp.
First
time
you
open
RStudio
you
will
be
asked
to
locate
the
folder
containing
R.
3) Subsequently,
once
you
have
opened
R
or
RStudio,
you
can
download
and
install
those
packages
that
you
want
from
CRAN,
via
the
Packages
>
Install
packages
menu
or
using
the
function
install.packages()
7
Installing
compilers
for
Mac
users:
Do
I
have
them
already?
Go
menu
>
Go
to
folder:
/usr/local/lib/
and
see
if
there
is
a
'gcc'
folder
and
'libgfortran...'
files.
No?
Then:
1) Go
to
the
Mac
App
store
and
download
Xcode
Development
Tools
and
follow
install
instructions.
For
OS10.6,
follow
the
instructions
here.
2) Download
the
compilers:
a. For
OS10.8
and
below:
go
to
CRAN
website
here
and
download
the
GNU
Fortran
compiler
(gfortran-‐4.2.3.pkg)
and
follow
install
instructions.
b. For
OS10.9
and
above:
Open
Terminal
(Applications/Utilities)
and
type
in
curl -O http://r.research.att.com/libs/gfortran-4.8.2-darwin13.tar.bz2
This
will
download
the
installer.
Then
type
sudo tar fvxz gfortran-4.8.2-darwin13.tar.bz2 -C /
This
will
install
the
compilers
into
the
/usr/local/lib/
folder.
The
command
sudo
will
ask
for
your
password.
Type
it
in,
but
note
it
will
not
appear
on
the
line.
Press
return.
The
terminal
window
will
fill
with
all
the
files
being
written.
(This
information
is
thanks
to
the
The
Coatless
Professor
who
troubleshooted
R
with
Mavericks).
3) Download
and
install
XQuartz
(X11)
if
it
is
not
already
on
your
Mac.
It
will
be
installed
in
the
Utilities
folder.
This
program
must
be
running
every
time
you
use
geomorph
(required
by
rgl).
This
is
a
short
version
of
information
available
here
and
here.
Thanks
to
Warren
Handley
(Flinders
University)
for
helping
troubleshoot
this
guide.
Installing
compilers
for
Windows
users:
Go
to
the
R
website
and
download
RTools.
Make
sure
to
download
the
correct
version!
Follow
the
install
instructions.
You
may
need
to
modify
the
path
(asked
during
the
installing).
Try
first
without
ticking
the
box
on
the
install
window.
If
running
install_github() about
does
not
work
then
reinstall
the
RTools
with
the
new
path
box
ticked).
Alternatively,
use
the
function
find_rtools() in
devtools
package.
For
more
information
for
Windows
users,
see
here.
8
IV. Workflows
for
common
analyses
Below
are
some
pathways
to
perform
common
analyses
in
geomorph.
This
is
not
an
exhaustive
list,
but
provides
a
reference
for
users
familiar
with
other
morphometric
software
to
navigate
the
functions.
In
red
the
type
of
question
or
analysis
is
presented,
and
in
blue
the
specific
geomorph
functions
in
sequence.
9
V. Example
datasets
in
geomorph
For
sections
2
through
4,
many
of
the
examples
will
be
using
data
included
with
geomorph.
There
are
nine
datasets:
plethodon,
scallops,
hummingbirds,
mosquito,
ratland,
plethspecies,
plethShapeFood,
motionpaths
and
scallopPLY.
To
load
type,
> data(plethodon)
It
is
advised
to
run
and
examine
these
example
datasets
before
performing
own
analyses
in
order
to
understand
how
a
function
and
its
options
work,
and
how
one’s
datasets
should
be
formatted.
> plethodon
$land
, , 1
[,1] [,2]
[1,] 8.89372 53.77644
[2,] 9.26840 52.77072
[3,] 5.56104 54.21028
[4,] 1.87340 52.75100
...
$links
[,1] [,2]
[1,] 4 5
[2,] 3 5
[3,] 2 4
[4,] 1 2
[5,] 1 3
[6,] 6 7
...
$species
[1] Jord Jord Jord Jord Jord Jord Jord Jord Jord Jord Teyah Teyah Teyah Teyah Teyah Teyah Teyah
[18] Teyah Teyah Teyah Jord Jord Jord Jord Jord Jord Jord Jord Jord Jord Teyah Teyah Teyah Teyah
[35] Teyah Teyah Teyah Teyah Teyah Teyah
Levels: Jord Teyah
$site
[1] Symp Symp Symp Symp Symp Symp Symp Symp Symp Symp Symp Symp Symp Symp Symp Symp Symp Symp Symp Symp
Allo
[22] Allo Allo Allo Allo Allo Allo Allo Allo Allo Allo Allo Allo Allo Allo Allo Allo Allo Allo Allo
Levels: Allo Symp
$outline
[,1] [,2]
[1,] 0.3986487 -0.2022766
[2,] 0.4000364 -0.2022312
[3,] 0.4014240 -0.2021857
[4,] 0.4028116 -0.2021400
[5,] 0.4041990 -0.2020943
[6,] 0.4055864 -0.2020484
...
The
dataset
above,
plethodon,
is
a
list
containing
four
components:
the
coordinate
data
(plethodon$land),
two
sets
of
grouping
variables
as
factors
(plethodon$species, plethodon$site),
the
wirelink
addresses
(plethodon$links),
and
an
matrix
of
outline
coordinates
for
visualizations
(plethodon$outline).
> class(plethodon$site)
[1] "factor"
> class(plethodon$land)
[1] "array"
> class(plethodon$links)
[1] "matrix"
10
Many
of
the
novice
user
problems
when
using
geomorph
and
R
stem
from
having
the
object
input
in
the
wrong
format.
Here
are
some
useful
base
functions
in
R
to
help
understand
formatting
of
one’s
data:
class() # Object Classes
attributes() # Object Attribute Lists
dim() # Dimensions of an Object
nrow() ; ncol() # The Number of Rows/Columns of a 2D array
dimnames() # Dimnames of an Object
names() # The Names of an Object
rownames() ; colnames() # Row and Column Names
is.numeric() # very useful to know if the data are numeric or not – dataframes often
do not preserved the data as numeric even though they are numbers
Geomorph
primarily
has
data
stored
in
a
2D
array
or
3D
array
(matrix
and
array
respectively)
(see
section
2.1),
grouping
variables
are
vectors
and
factors,
and
outputs
of
functions
may
be
lists.
For
more
information
about
the
object
classes
in
R
see
http://www.statmethods.net/input/datatypes.html
An
expression
of
the
form
y ~ model is
interpreted
as
a
specification
that
the
response
y
is
modelled
by
a
linear
predictor
specified
symbolically
by
model.
Finally,
this
manual
only
covers
geomorph
functions.
It
is
recommended
that
users
look
to
some
“getting
started
with
R”
resources,
such
as
Quick-‐R
(http://www.statmethods.net/),
and
the
R
Introduction
manual
on
(http://cran.r-‐project.org/doc/manuals/R-‐intro.pdf),
and
various
Springer
eBooks
in
the
series
‘Use
R!’.
Also
highly
recommended
is
J.
Claude’s
book
Morphometric
with
R
(2008).
12
Section
2:
Data
Input:
Importing
landmark
data
1.1 TPS
files
(readland.tps)
Function:
readland.tps(file, specID = c("None", "ID", "imageID"), readcurves = FALSE,
warnmsg = T)
Arguments:
file
A
*.tps
file
containing
two-‐
or
three-‐dimensional
landmark
data
specID
a
character
specifying
whether
to
extract
the
specimen
ID
names
from
the
ID
or
IMAGE
lines
(default
is
"None")
readcurves
A
logical
value
stating
whether
CURVES=
field
and
associated
coordinate
data
will
be
read
as
semilandmarks
(TRUE)
or
ignored
(FALSE)
warnmsg
A
logical
value
stating
whether
warnings
should
be
printed
This
function
reads
a
*.tps
file
containing
two-‐
or
three-‐dimensional
landmark
coordinates
for
a
set
of
specimens.
Tps
files
are
text
files
in
one
of
the
standard
formats
for
geometric
morphometrics
(see
Rohlf
2010).
Two-‐dimensional
landmarks
coordinates
are
designated
by
the
identifier
"LM=",
while
three-‐dimensional
data
are
designated
by
"LM3=".
Landmark
coordinates
are
multiplied
by
their
scale
factor
if
this
is
provided
for
all
specimens.
If
one
or
more
specimens
are
missing
the
scale
factor
(there
is
no
line
“SCALE=”),
landmarks
are
treated
in
their
original
units.
The
name
of
the
specimen
can
be
given
in
the
tps
file
by
“ID=”
(use
specID=”ID”)
or
“IMAGE=”
(use
specID= “imageID”),
otherwise
the
function
defaults
to
specID= “None”.
If
there
are
curves
defined
in
the
file
(i.e.,
CURVES=
fields),
the
option
readcurves
should
be
used.
When
readcurves = TRUE,
the
coordinate
data
for
the
curves
will
be
returned
as
semilandmarks
and
will
be
appended
to
the
fixed
landmark
data.
Then
the
user
needs
to
use
define.sliders()
to
create
a
matrix
designating
how
the
curve
points
will
slide
(used
by
'curves='
in
gpagen).
When
readcurves =
FALSE,
only
the
landmark
data
are
returned
(the
curves
are
ignored).
At present, all other information that can be contained in tps files (comments, variables, radii, etc.) is ignored.
ratland.tps
LM=8
-0.45 -0.475
-0.59 -0.28
-0.515 -0.12
-0.33 0
0 0
0.145 -0.395
-0.045 -0.42
-0.26 -0.465
ID = specimen103N
LM=8
...
13
[3,] -0.515 -0.120
[4,] -0.330 0.000
[5,] 0.000 0.000
[6,] 0.145 -0.395
[7,] -0.045 -0.420
[8,] -0.260 -0.465
In
this
case,
there
is
no
scale
given
in
the
tps
file,
so
the
command
warns
that
the
data
are
treated
in
their
original
units.
The
function
returns
a
3D
array
containing
the
coordinate
data,
and
if
provided
in
the
file,
the
names
of
the
specimens
(dimnames(mydata)[[3]]).
Function
reads
a
single
*.nts
file
containing
a
matrix
of
two-‐
or
three-‐dimensional
landmark
coordinates
for
a
set
of
specimens.
NTS
files
are
text
files
in
one
of
the
standard
formats
for
geometric
morphometrics
(see
Rohlf
2012).
The
parameter
line
contains
5
or
6
elements,
and
must
begin
with
a
"1"
to
designate
a
rectangular
matrix.
The
second
and
third
values
designate
how
many
specimens
(n)
and
how
many
total
variables
(p
x
k)
are
in
the
data
matrix.
The
fourth
value
is
a
"0"
if
the
data
matrix
is
complete
and
a
"1"
if
there
are
missing
values.
If
missing
values
are
present,
the
'1'
is
followed
by
the
arbitrary
numeric
code
used
to
represent
missing
values
(e.g.,
-‐999).
These
values
will
be
replaced
with
"NA"
in
the
output
array.
The
final
value
of
the
parameter
line
denotes
the
dimensionality
of
the
landmarks
(2,3)
and
begins
with
"DIM=".
If
specimen
and
variable
labels
are
included,
these
are
designated
placing
an
"L"
immediately
following
the
specimen
or
variable
values
in
the
parameter
file.
The
labels
then
precede
the
data
matrix.
Here
there
are
n
=
44
and
p*k
=
50
(25
2D
landmarks).
rats.nts
" rats data, 164 rats, 8 landmarks in 2 dimensions
1 164 16 0 dim=2
-.450 -.475 -.590 -.280 -.515 -.120 -.330 0 0 0 .145 -.395 -.045 -.420 -.260 -.465
-.530 -.555 -.685 -.320 -.625 -.120 -.400 0 0 0 .230 -.425 -.005 -.480 -.265 -.525
-.560 -.570 -.700 -.335 -.670 -.120 -.425 0 0 0 .300 -.440 .015 -.495 -.270 -.540
-.590 -.580 -.745 -.355 -.700 -.100 -.435 0 0 0 .330 -.445 .030 -.505 -.285 -.565
-.650 -.580 -.800 -.340 -.715 -.090 -.450 0 0 0 .360 -.445 .040 -.515 -.300 -.580
...
The
function
returns
a
3D
array
containing
the
coordinate
data,
and
if
provided
in
the
file,
the
names
of
the
specimens
(dimnames(mydata)[[3]]).
Function
is
for
*.nts
file
containing
landmark
coordinates
for
multiple
specimens.
Note
that
*.dta
files
in
the
nts
format
written
by
Landmark
Editor
http://graphics.idav.ucdavis.edu/research/projects/EvoMorph,
and
*.nts
files
written
by
Stratovan
Checkpoint
http://www.stratovan.com/
have
incorrect
header
notation;
every
header
is
1
n
p-‐x-‐k
1
9999
Dim=3,
rather
than
1
n
p-‐x-‐k
0
Dim=3,
which
denotes
that
missing
data
is
in
the
file
even
when
it
is
not.
NAs
will
be
introduced
unless
the
header
is
manually
altered.
14
1.3 Multiple
NTS
files
of
single
specimens
(readmulti.nts)
Function:
readmulti.nts(file)
This
function
reads
a
list
containing
the
names
of
multiple
*.nts
files,
where
each
*.nts
file
contains
the
landmark
coordinates
for
a
single
specimen,
e.g.
made
by
digit.fixed().
For
these
files,
the
number
of
variables
(columns)
of
the
data
matrix
will
equal
the
number
of
dimensions
of
the
landmark
data
(k
=
2
or
3).
The
parameter
line
contains
5
or
6
elements,
and
must
begin
with
a
"1"
to
designate
a
rectangular
matrix.
The
second
and
third
values
designate
the
number
of
landmarks
(p)
and
the
dimensionality
of
the
data
(k)
in
the
data
matrix.
The
fourth
value
is
a
"0"
if
the
data
matrix
is
complete
and
a
"1"
if
there
are
missing
values.
If
missing
values
are
present,
the
'1'
is
followed
by
the
arbitrary
numeric
code
used
to
represent
missing
values
(e.g.,
-‐999).
These
values
will
be
replaced
with
"NA"
in
the
output
array.
The
final
value
of
the
parameter
line
denotes
the
dimensionality
of
the
landmarks
(2,3)
and
begins
with
"DIM=".
The
specimen
label
is
extracted
from
the
file
name,
not
the
header.
Here
is
an
example
of
3
.nts
files,
each
p
=
166,
k
=
3.
These
are
then
read
and
concatenated
into
a
single
3D
array
for
all
specimens.
> filelist <- list.files(pattern = ".nts")
> filelist
[1] “ball01L.nts” “ball02L.nts” “ball03L.nts” ...
ball01L.nts
"ball01L
1 166 3 0 dim=3
37.366242091765 -19.7782715772904 -1.45757328357893
45.336342091765 -15.9657715772904 -4.28288328357893
45.562042091765 -1.20527157729041 -5.17616328357893
47.607342091765 13.3546284227096 -6.41333328357893
39.940142091765 18.5793284227096 -4.27434328357893
-44.504657908235 0.138928422709595 -5.40957328357893
-2.61418790823501 47.4933284227096 -3.09240328357893
-8.00038890823501 -45.0109715772904 2.45829671642107
30.500142091765 35.9411284227096 -2.80191328357893
...
> mydata <- readmulti.nts(filelist)
> mydata
, , ball01L
The
function
returns
a
3D
array
containing
the
coordinate
data,
and
the
names
of
the
specimens
(dimnames(mydata)[[3]])
extracted
from
the
file
names.
15
1.4 Morphologika
files
(read.morphologika)
Function:
read.morphologika(file)
This
function
reads
a
*.txt
file
in
the
Morphologika
format
containing
two-‐
or
three-‐dimensional
landmark
coordinates.
Morphologika
files
are
text
files
in
one
of
the
standard
formats
for
geometric
morphometrics
(see
O'Higgins
and
Jones
1998),
see
http://sites.google.com/site/hymsfme/resources.
If
the
headers
"[labels]"
,
"[labelvalues]"
and
"[groups]"
are
present
in
the
file,
then
a
data
matrix
containing
all
individual
specimen
information
is
returned.
If
the
header
"[wireframe]"
is
present,
then
a
matrix
of
the
landmark
addresses
for
the
wireframe
is
returned.
morphologikaexample.txt
[individuals]
15
[landmarks]
31
[Dimensions]
3
[names]
Specimen 1
Specimen 2
Specimen 3
...
Specimen 15
[labels]
Sex
[labelvalues]
Female
Female
...
Female
[rawpoints]
'#1
16.01 24.17 11.18
15 24.86 11.16
14.96 25.54 11.52
16.26 24.36 11.48
15.89 26.61 11.83
17.16 25.33 12.35
18.22 23.65 11.12
...
> mydata <- read.morphologika("morphologikaexample.txt")
> mydata$coords[,,1]
[,1] [,2] [,3]
[1,] 16.01 24.17 11.18
[2,] 15.00 24.86 11.16
[3,] 14.96 25.54 11.52
[4,] 16.26 24.36 11.48
[5,] 15.89 26.61 11.83
[6,] 17.16 25.33 12.35
...
> mydata$labels
Sex
Specimen 1 "Female"
Specimen 2 "Female"
Specimen 3 "Female"
Specimen 4 "Female"
Specimen 5 "Male"
Specimen 6 "Male"
...
16
The
function
returns
a
3D
array
containing
the
coordinate
data,
and
if
provided,
the
names
of
the
specimens
(dimnames(mydata)[[3]]).
If
other
optional
headers
are
present
in
the
file
(e.g.,
"[labels]"
or
"[wireframe]")
function
returns
a
list
containing
the
3D
array
of
coordinates
($coords),
and
a
data
matrix
of
the
data
from
labels
($labels)
and/or
the
landmark
addresses
denoting
the
wireframe
($wireframe)
–
which
can
be
passed
to
plotRefToTarget()
option
'links'.
To
read
multiple
Morphologika
files
that
each
contain
a
single
specimen,
download
this
file
(https://github.com/EmSherratt/MorphometricSupportCode/blob/master/read.multi.morphologika.
R)
put
in
the
working
directory
then
to
use:
> source("read.multi.morphologika.R")
> filelist <- list.files(pattern = "*.txt") # list all morpholgika files
> mydata <- read.multi.morphologika("morphologikaexample.txt")
Using
base
read
functions
in
R,
one
can
read
in
data
by
many
other
ways.
Here
are
two
examples.
These
examples
use
data
arrangement
function
arrayspecs()
(see
section
2.1
for
details)
and
creates
an
object
in
the
same
way
as
the
previous
functions.
e.g.
For
a
set
of
files
(file1.txt,
file2.txt,
file3.txt...)
each
containing
the
landmark
coordinates
of
a
single
specimen
file1.txt
16.01 24.17 11.18
15 24.86 11.16
14.96 25.54 11.52
16.26 24.36 11.48
15.89 26.61 11.83
17.16 25.33 12.35
18.22 23.65 11.12
...
> filelist <- list.files(pattern = ".txt") # makes a list of all .txt files in
working directory
> names <- gsub (".txt", "", filelist) # extracts names of specimens from the file
name
> coords = NULL # make an empty object
> for (i in 1:length(filelist)){
tmp <- as.matrix(read.table(filelist[i]))
coords <- rbind(coords, tmp)
}
> coords <- arrayspecs(coords, p, k)
> dimnames(coords)[[3]] <- names
17
e.g.
For
a
single
file
containing
the
landmark
coordinates
of
a
set
of
specimens,
where
each
row
is
a
specimen,
and
coordinate
data
arranged
in
columns
x1,
y1,
x2,
y2…
etc.,
and
the
first
column
is
the
ID
of
the
specimens,
e.g.,
from
a
data
file
exported
from
MorphoJ.
coordinatedata.txt
ID X1 Y1 X2 Y2 X3 Y3 ...
specimen1 0.595 0.1679 0.2232 0.5028 1.292 0.4237 0.51 ...
specimen2 0.0038 1.3925 0.7966 0.4132 0.1006 0.8483 ...
specimen3 0.6249 0.4515 0.3576 1.3262 0.9114 0.3611 ...
...
> mydata <- read.table("coordinatedata.txt",header=TRUE,row.names=1,
stringsAsFactors = FALSE)
# The stringsAsFactors = FALSE is VERY important here
# Here row.names = 1 means “set the row names of the object to be the values in
column 1”.
> is.numeric(mydata)
[1] FALSE # here R tells us the data are not numeric, even though we can see they
are if we use View(mydata). Why? Because if there are characters in the file, all
elements are automatically read as characters not numerical data
#The solution is to force those to be numeric with: as.matrix(). For example, say we
know the shape coordinates are present in the file after two columns of non-shape
coordinates (these could be centroid size, or a classifier), then:
> coords <- as.matrix(mydata[,-(1:2)]) # here we say, use all columns except the
first two.
> is.numeric(shape)
[1] TRUE # now it's numeric 2D array
> coords <- arrayspecs(coords, p, k) # makes the matrix a 3D array
If
the
data
file
contains
classifier
variables,
these
can
be
extracted
by
subsetting
columns.
For
example,
if
the
classifiers
are
in
the
first
two
columns,
then:
> classifiers <- mydata[ ,1:2] # and if they are classifiers, they will probably
need to be factors so:
> classifiers <- factor(classifiers)
18
Section
2:
Data
Preparation:
Manipulating
landmark
data
and
classifiers
2.1 Data
object
formats
Landmark
data
in
geomorph
can
be
found
as
objects
in
two
formats:
a
2D
array
(matrix;
Figure
2A)
or
a
3D
array
(Figure
2B).
These
data
formats
follow
the
convention
in
other
morphometric
packages
(e.g.,
shapes,
Morpho)
and
in
J.Claude’s
book
Morphometrics
in
R
(2008).
B(
A(
X1# Y1# Z1# X2# Y2# Z2# X3# Y3# ...# Xp#
#
Specimen#1#
Specimen#2# Specimen(n(
Specimen#3#
...# Specimen(3(
Specimen#n# Specimen(2(
Specimen(1(
Figure
2
Schematic
of
a
2D
array
(A)
and
a
3D
array
(B).
This
example
shows
3D
landmark
coordinate
data,
but
the
same
format
would
be
used
for
2D
coordinates
2.3 Converting
a
3D
array
into
a
2D
array
(two.d.array)
Function:
two.d.array(A)
This
function
converts
a
3D
array
(p
x
k
x
n)
of
landmark
coordinates
into
a
2D
array
(n
x
[p
x
k]).
The
latter
format
of
the
shape
data
is
useful
for
performing
subsequent
statistical
analyses
in
R
(e.g.,
PCA,
MANOVA,
PLS,
etc.).
Row
labels
are
preserved
if
included
in
the
original
array.
> a <- two.d.array(mydata) # where mydata is a 3D array
> a
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 8.893720 53.77644 9.268400 52.77072 5.561040 54.21028 1.873400 52.75100 1.281800 53.18484
[2,] 8.679762 54.57819 8.935628 53.83027 5.451914 54.65691 1.987882 52.68871 1.515514 53.02331
[3,] 9.805328 56.06903 10.137712 55.27961 6.647680 55.73664 3.448484 53.86698 3.012230 54.34478
[4,] 9.637164 58.03294 9.952104 56.77318 6.109836 57.94896 2.645496 55.89135 2.015616 56.62621
[5,] 11.035692 58.75009 11.335110 57.85184 8.255382 58.92119 4.555431 57.46687 3.956595 58.08709
...
20
If
the
data
have
many
specimens
or
many
different
groups,
it
may
be
easier
to
make
a
table
in
excel,
save
as
a
.csv
file
and
import
using
read.csv().
classifier.csv
ID# Species# Habitat#
specimen1# A.species# dry#
specimen2# A.notherspecies# wet#
specimen3# A.species# dry#
specimen4# A.species# dry#
specimen5# A.species# wet#
specimen6# A.notherspecies# wet#
specimen7# A.notherspecies# wet#
specimen8# A.notherspecies# wet#
specimen9# A.notherspecies# dry#
...# ...# ...#
2.5 Lists
Another
common
data
structure
in
R
is
a
list.
In
essence,
a
list
is
a
generic
vector
containing
other
objects.
In
geomorph,
the
example
data
are
all
lists.
e.g.
plethodon:
> data(plethodon)
> attributes(plethodon)
$names
[1] "land" "links" "species" "site" "outline"
Here,
plethodon
is
made
up
of
5
named
objects
(which
are
each
vectors,
matrices/2D
arrays
or
3D
arrays).
To
access
named
objects
within
a
list,
use
$,
such
as
plethodon$links.
The
returned
output
of
many
geomorph
functions
is
also
in
named
list
form.
Parts
of
a
list
can
also
be
accessed
using
numbers
with
double
square
brackets
[[]].
So
in
the
above
example.
links
is
the
2nd
object
in
the
plethodon
list,
and
so
can
also
be
accessed
by
plethodon[[2]].
For
more
details
on
this,
a
good
resource
is
the
website
R
tutorial
(http://www.r-‐tutor.com/r-‐
introduction/list).
21
2.6 Estimating
missing
landmarks
(estimate.missing)
All
analysis
and
plotting
functions
in
geomorph
require
a
full
complement
of
landmark
coordinates.
Either
the
missing
values
are
estimated,
or
subsequent
analyses
are
performed
on
a
subset
dataset
excluding
specimens
with
missing
values.
Below
is
the
function
to
estimate
missing
data,
followed
by
steps
of
how
to
just
exclude
specimens
with
missing
values.
Function:
estimate.missing(A, method = c("TPS", "Reg"))
Arguments:
A
A
3D
array
(p
x
k
x
n)
containing
landmark
coordinates
for
a
set
of
specimens
method
Method
for
estimating
missing
landmark
locations
The
function
estimates
the
locations
of
missing
landmarks
for
incomplete
specimens
in
a
set
of
landmark
configurations,
where
missing
landmarks
in
the
incomplete
specimens
are
designated
by
NA
in
place
of
the
x,y,z
coordinates.
Two
distinct
approaches
are
implemented.
The
first
approach
(method="TPS")
uses
the
thin-‐plate
spline
to
interpolate
landmarks
on
a
reference
specimen
to
estimate
the
locations
of
missing
landmarks
on
a
target
specimen.
Here,
a
reference
specimen
is
obtained
from
the
set
of
specimens
for
which
all
landmarks
are
present,
Next,
each
incomplete
specimen
is
aligned
to
the
reference
using
the
set
of
landmarks
common
to
both.
Finally,
the
thin-‐plate
spline
is
used
to
estimate
the
locations
of
the
missing
landmarks
in
the
target
specimen
(Gunz
et
al.
2009).
The
second
approach
(method="Reg")
is
multivariate
regression.
Here
each
landmark
with
missing
values
is
regressed
on
all
other
landmarks
for
the
set
of
complete
specimens,
and
the
missing
landmark
values
are
then
predicted
by
this
linear
regression
model.
Because
the
number
of
variables
can
exceed
the
number
of
specimens,
the
regression
is
implemented
on
scores
along
the
first
set
of
PLS
axes
for
the
complete
and
incomplete
blocks
of
landmarks
(see
Gunz
et
al.
2009).
One
can
also
exploit
bilateral
symmetry
to
estimate
the
locations
of
missing
landmarks.
Several
possibilities
exist
for
implementing
this
approach
(see
Gunz
et
al.
2009).
Example
R
code
for
one
implementation
is
found
in
Claude
(2008).
Missing
landmarks
in
a
target
specimen
are
designated
by
NA
in
place
of
the
x,y,z
coordinates.
To
make
this
so,
> any(is.na(mydata) # check if there are NAs in the data
FALSE # if false then,
> mydata[which(mydata == -999)] <- NA #change missing values from “-999” to NAs
Here
is
an
example
using
Plethodon
dataset,
> data(plethodon)
> plethland<-plethodon$land
> plethland[2,,2]<-plethland[6,,2]<-NA #create missing landmarks
> plethland[2,,5]<-plethland[6,,5]<-NA
> plethland[2,,10]<-NA
> estimate.missing(plethland,method="TPS")
> estimate.missing(plethland,method="Reg")
The function returns a 3D array with the missing landmarks estimated.
22
Instead
of
estimating
missing,
an
alternative
is
to
proceed
with
the
specimens
for
which
data
are
missing
excluded.
For
example
to
make
a
dataset
of
only
the
complete
specimens
(starting
with
the
dataset
as
2D
array),
two
ways
are
possible:
> mydata
[,1] [,2] [,3] [,4]
[1,] 8.893720 53.77644 9.268400 52.77072
[2,] 8.679762 54.57819 8.935628 53.83027
[3,] 9.805328 56.06903 NA NA
[4,] 9.637164 58.03294 9.952104 56.77318
[5,] NA NA 11.335110 57.85184
[6,] 7.946625 55.71114 8.476400 54.82112
[7,] 8.849841 58.66961 9.396387 57.82877
[8,] 9.331504 56.36904 10.154872 55.31344
> newdata <- mydata[complete.cases(mydata),] # keep only specimens with complete
data
> # OR
> newdata <- na.omit(mydata) # use only specimens without NAs
> newdata
[,1] [,2] [,3] [,4]
[1,] 8.893720 53.77644 9.268400 52.77072
[2,] 8.679762 54.57819 8.935628 53.83027
[3,] 9.637164 58.03294 9.952104 56.77318
[4,] 7.946625 55.71114 8.476400 54.82112
[5,] 8.849841 58.66961 9.396387 57.82877
[6,] 9.331504 56.36904 10.154872 55.31344
These
same
functions
can
be
used
to
make
a
dataset
of
only
the
landmarks
in
all
specimens,
by
inputting
the
matrix
mydata
in
transpose,
e.g.,
t(mydata).
Note
that
these
methods
will
re-‐label
the
specimen
or
landmark
numbers.
23
2.7 Rotate
a
subset
of
2D
landmarks
to
common
articulation
angle
(fixed.angle)
A
function
for
rotating
a
subset
of
landmarks
so
that
the
articulation
angle
between
subsets
is
constant.
Presently,
the
function
is
only
implemented
for
two-‐dimensional
landmark
data.
Function:
fixed.angle(A, art.pt = NULL, angle.pts = NULL, rot.pts = NULL,
angle = 0, degrees = FALSE)
Arguments:
A
A
3D
array
(p
x
k
x
n)
containing
landmark
coordinates
for
a
set
of
specimens
art.pt
A
number
specifying
which
landmark
is
the
articulation
point
between
the
two
landmark
subsets
angle.pts
A
vector
containing
numbers
specifying
which
two
points
used
to
define
the
angle
(one
per
subset)
rot.pts
A
vector
containing
numbers
specifying
which
landmarks
are
in
the
subset
to
be
rotated
angle
An
optional
value
specifying
the
additional
amount
by
which
the
rotation
should
be
augmented
(in
radians)
degrees
A
logical
value
specifying
whether
the
additional
rotation
angle
is
expressed
in
degrees
or
radians
(radians
is
default)
This
function
standardizes
the
angle
between
two
subsets
of
landmarks
for
a
set
of
specimens.
The
approach
assumes
a
simple
hinge-‐point
articulation
between
the
two
subsets,
and
rotates
all
specimens
such
that
the
angle
between
landmark
subsets
is
equal
across
specimens
(see
Adams
1999).
As
a
default,
the
mean
angle
is
used,
though
the
user
may
specify
an
additional
amount
by
which
this
may
be
augmented.
Example
using
Plethodon.
Articulation
point
is
landmark
1,
rotate
mandibular
landmarks
(2-‐5)
relative
to
cranium
> data(plethspecies)
> fixed.angle(plethspecies$land,art.pt=1,angle.pts=c(5,6),rot.pts=c(2,3,4,5))
Before
After
Function
returns
a
3D
array
containing
the
newly
rotated
data.
24
Section
3a:
Generalized
Procrustes
Analysis
3.1 Generalized
Procrustes
Analysis
(gpagen)
Generalized
Procrustes
Analysis
(GPA:
Gower
1975;
Rohlf
and
Slice
1990)
is
the
primary
means
by
which
shape
variables
are
obtained
from
landmark
data
(for
a
general
overview
of
geometric
morphometrics
see
Bookstein
1991;
Rohlf
and
Marcus
1993;
Adams
et
al.
2004;
Mitteroecker
and
Gunz
2009;
Zelditch
et
al.
2012;
Adams
et
al.
2013).
GPA
translates
all
specimens
to
the
origin,
scales
them
to
unit-‐centroid
size,
and
optimally
rotates
them
(using
a
least-‐squares
criterion)
until
the
coordinates
of
corresponding
points
align
as
closely
as
possible.
The
resulting
aligned
Procrustes
coordinates
represent
the
shape
of
each
specimen,
and
are
found
in
a
curved
space
related
to
Kendall's
shape
space
(Kendall
1984).
Typically,
these
are
projected
into
a
linear
tangent
space
yielding
Kendall's
tangent
space
coordinates
(Dryden
and
Mardia
1993;
Rohlf
1999),
which
are
used
for
subsequent
multivariate
analyses.
Additionally,
any
semilandmarks
on
curves
and
are
slid
along
their
tangent
directions
or
tangent
planes
during
the
superimposition
(see
Bookstein
1997;
Gunz
et
al.
2005).
Presently,
two
implementations
are
possible:
1)
the
locations
of
semilandmarks
can
be
optimized
by
minimizing
the
bending
energy
between
the
reference
and
target
specimen
(Bookstein
1997),
or
by
minimizing
the
Procrustes
distance
between
the
two
(Rohlf
2010).
The
first
step
in
any
geometric
morphometric
analysis
is
to
perform
a
Procrustes
superimposition
of
the
raw
coordinate
data
(read
in
using
functions
in
Section
1).
Function:
gpagen(A, Proj = TRUE, ProcD = TRUE, PrinAxes = TRUE, ShowPlot = TRUE, curves = NULL,
surfaces = NULL, ...)
Arguments:
A
A
3D
array
(p
x
k
x
n)
containing
landmark
coordinates
for
a
set
of
specimens
Proj
A
logical
value
indicating
whether
or
not
the
aligned
Procrustes
residuals
should
be
projected
into
tangent
space
ProcD
A
logical
value
indicating
whether
or
not
Procrustes
distance
should
be
used
as
the
criterion
for
optimizing
the
positions
of
semilandmarks
PrinAxes
A
logical
value
indicating
whether
or
not
to
align
the
shape
data
by
principal
axes
ShowPlot
A
logical
value
indicating
whether
or
not
a
plot
of
Procrustes
residuals
should
be
displayed
curves
An
optional
matrix
defining
which
landmarks
should
be
treated
as
semilandmarks
on
boundary
curves,
and
which
landmarks
specify
the
tangent
directions
for
their
sliding
(see
define.sliders())
surfaces
An
optional
vector
defining
which
landmarks
should
be
treated
as
semilandmarks
on
surfaces
...
Options
to
be
passed
to
plotAllSpecimens().
The
function
performs
a
Generalized
Procrustes
Analysis
(GPA)
on
two-‐dimensional
or
three-‐
dimensional
landmark
coordinates.
The
analysis
can
be
performed
on
fixed
landmark
points,
semilandmarks
on
curves,
semilandmarks
on
surfaces,
or
any
combination.
To
include
semilandmarks
on
curves,
one
must
specify
a
matrix
defining
which
landmarks
are
to
be
treated
as
semilandmarks
using
the
"curves="
option
(this
matrix
can
be
made
using
define.sliders(), see
section
5).
Likewise,
to
include
semilandmarks
on
surfaces,
one
must
specify
a
vector
listing
which
landmarks
are
to
be
treated
as
surface
semilandmarks
using
the
"surfaces="
option.
The
"ProcD=TRUE"
option
will
slide
the
semilandmarks
along
their
tangent
directions
using
the
Procrustes
distance
criterion,
while
"ProcD=FALSE"
will
slide
the
semilandmarks
based
on
minimizing
bending
energy.
The
aligned
Procrustes
residuals
can
be
projected
into
tangent
space
using
the
"Proj=TRUE"
option.
NOTE:
Large
datasets
may
exceed
the
memory
limitations
of
R.
25
If
the
curve
semilandmarks
were
defined
by
define.sliders(),
or
the
surface
semilandmarks
digitized
with
buildtemplate()
and
digitizesurface()
the
.csv
files
these
functions
make
must
be
first
read
in
as
follows:
> curves <- as.matrix(read.csv("curveslide.csv", header=T))
> sliders <- as.matrix(read.csv("surfslide.csv", header=T))
Example
using
fixed
points
only:
> data(plethodon)
> Y <- gpagen(plethodon$land)
> Y
$coords
, , 1
[,1] [,2]
[1,] 0.18705239 -0.023704219
[2,] 0.21178322 -0.089958949
[3,] -0.03236886 0.004834644
[4,] -0.27528209 -0.091255419
[5,] -0.31422144 -0.062671167
[6,] -0.31685794 -0.053529677
[7,] -0.34273719 0.037340225
...
$Csize
[1] 15.226920 14.718881 14.009548 15.750465 13.935179 13.506818 13.593187 16.020895 15.641445 16.380327
[11] 19.083462 16.930622 18.426860 9.581975 19.688119 18.233979 11.290599 18.980799 17.009811 17.067253
...
The
function
returns
a
list
containing
the
Procrustes
coordinates
($coords),
the
centroid
sizes
($Csize)
and,
if
ShowPlot=T
a
graph
of
the
specimens
(grey)
around
the
mean
(black)
shape:
Example
using
fixed
points
and
semilandmarks
on
curves:
> data(hummingbirds)
> hummingbirds$curvepts # Matrix defining which points are semilandmarks (middle
column) and in which directions they slide (columns 1 vs. 3)
before slide after
[1,] 1 11 12
[2,] 11 12 13
[3,] 13 14 15
[4,] 7 15 14
26
[5,] 12 13 14
[6,] 1 16 17
[7,] 16 17 18
[8,] 17 18 19
...
> #Using Procrustes Distance for sliding
> Y <- gpagen(hummingbirds$land,curves=hummingbirds$curvepts)
> Y
$coords
, , 1
[,1] [,2]
[1,] -0.24134653 -0.035692519
[2,] -0.23007167 -0.034486535
[3,] -0.13498860 -0.007088872
[4,] -0.11202212 -0.002656968
[5,] 0.25340294 0.035622930
...
$Csize
[1] 2538.998 2683.454 2659.923 2715.072 2640.722 2779.321 2547.102 2717.373 2626.064 2870.187 2631.083 ...
27
Example
using
fixed
points,
curves
and
surfaces:
> data(scallops)
> scallops$curvslide # Matrix defining which points are semilandmarks (middle
column) and in which directions they slide (columns 1 vs. 3)
before slide after
[1,] 5 6 7
[2,] 6 7 8
[3,] 7 8 9
[4,] 8 9 10
[5,] 9 10 11
[6,] 10 11 12
...
> scallops$surfslide # Matrix (1 column) defining which points are semilandmarks to
slide over the surface
[,1]
[1,] 17
[2,] 18
[3,] 19
[4,] 20
[5,] 21
[6,] 22
...
> #Using Procrustes Distance for sliding
> Y <- gpagen(A=scallops$coorddata, curves=scallops$curvslide,
surfaces=scallops$surfslide)
> Y
$coords
, , ZXkuhn01Lxcoords
For
3D
data,
the
Procrustes
data
are
plotted
in
the
rgl
window.
For
all
subsequent
analyses,
the
Procrustes
coordinates
(Y$coords )
should
be
used.
28
3.2 Generalized
Procrustes
Analysis
with
Bilateral
Symmetry
Analysis
(bilat.symmetry)
If
the
data
has
bilateral
symmetry,
the
first
step
is
to
perform
a
superimposition
of
the
raw
coordinate
data
taking
into
account
the
symmetry.
This
function
also
assesses
the
statistical
differences
in
the
symmetric
data.
Function:
bilat.symmetry(A, ind = NULL, side = NULL, replicate = NULL,
object.sym = FALSE, land.pairs = NULL, warpgrids = TRUE, mesh = NULL,
verbose = FALSE)
Arguments:
A
A
3D
array
(p
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
a
set
of
specimens
[for
"object.sym=FALSE,
A
is
of
dimension
(n
x
k
x
2n)]
ind
A
vector
containing
labels
for
each
individual.
For
matching
symmetry,
the
matched
pairs
receive
the
same
label
(replicates
also
receive
the
same
label).
side
An
optional
vector
(for
matching
symmetry)
designating
which
object
belongs
to
which
'side-‐group'
replicate
An
optional
vector
designating
which
objects
belong
to
which
group
of
replicates
object.sym
A
logical
value
specifying
whether
the
analysis
should
proceed
based
on
object
symmetry
=TRUE
or
matching
symmetry
=FALSE
land.pairs
An
optional
matrix
(for
object
symmetry)
containing
numbers
for
matched
pairs
of
landmarks
across
the
line
of
symmetry
warpgrids
A
logical
value
indicating
whether
deformation
grids
for
directional
and
fluctuating
components
of
asymmetry
mesh
A
mesh3d
object
to
be
warped
to
represent
shape
deformation
of
the
directional
and
fluctuating
components
of
asymmetry
if
warpgrids= TRUE
(see
warpRefMesh).
verbose
A
logical
value
indicating
whether
the
output
is
basic
or
verbose
The
function
quantifies
components
of
shape
variation
for
a
set
of
specimens
as
described
by
their
patterns
of
symmetry
and
asymmetry.
Here,
shape
variation
is
decomposed
into
variation
among
individuals,
variation
among
sides
(directional
asymmetry),
and
variation
due
to
an
individual
x
side
interaction
(fluctuating
symmetry).
These
components
are
then
statistically
evaluated
using
Procrustes
ANOVA
and
Goodall's
F
tests
(i.e.,
an
isotropic
model
of
shape
variation).
Methods
for
both
matching
symmetry
and
object
symmetry
can
be
implemented.
Matching
symmetry
is
when
each
object
contains
mirrored
pairs
of
structures
(e.g.,
right
and
left
hands)
while
object
symmetry
is
when
a
single
object
is
symmetric
about
a
midline
(e.g.,
right
and
left
sides
of
human
faces).
Analytical
and
computational
details
concerning
the
analysis
of
symmetry
in
geometric
morphometrics
can
be
found
in
Mardia
et
al.
(2000)
and
Klingenberg
et
al.
(2002).
Analyses
of
symmetry
for
matched
pairs
of
objects
is
implemented
when
object.sym=FALSE.
Here,
a
3D
array
[p
x
k
x
2n]
contains
the
landmark
coordinates
for
all
pairs
of
structures
(2
structures
for
each
of
n
specimens).
Because
the
two
sets
of
structures
are
on
opposite
sides,
they
represent
mirror
images,
and
one
set
must
be
reflected
prior
to
the
analysis
to
allow
landmark
correspondence.
It
is
assumed
that
the
user
has
done
this
prior
to
performing
the
symmetry
analysis.
Reflecting
a
set
of
specimens
may
be
accomplished
by
multiplying
one
coordinate
dimension
by
'-‐1'
for
these
structures
(either
the
x-‐,
the
y-‐,
or
the
z-‐dimension).
A
vector
containing
information
on
individuals
and
sides
must
also
be
supplied.
Replicates
of
each
specimen
may
also
be
included
in
the
dataset,
and
when
specified
will
be
used
as
measurement
error
(see
Klingenberg
and
McIntyre
1998).
Analyses
of
object
symmetry
is
implemented
when
object.sym=TRUE.
Here,
a
3D
array
[p
x
k
x
n]
contains
the
landmark
coordinates
for
all
n
specimens.
To
obtain
information
about
asymmetry,
the
function
generates
a
second
set
of
objects
by
reflecting
them
about
one
of
their
coordinate
axes.
The
landmarks
across
the
line
of
symmetry
are
then
relabeled
to
obtain
landmark
correspondence.
The
user
must
supply
a
list
of
landmark
pairs.
A
vector
containing
information
on
individuals
must
also
be
29
supplied.
Replicates
of
each
specimen
may
also
be
included
in
the
dataset,
and
when
specified
will
be
used
as
measurement
error.
Example
of
matching
symmetry:
> data(mosquito)
> bilat.symmetry(mosquito$wingshape,ind=mosquito$ind,side=mosquito$side,
replicate=mosquito$replicate,object.sym=FALSE, verbose=F)
[1] "No specimen names in response matrix. Assuming specimens in same order."
$ANOVA.size
df SS MS F P
ind 9 4.1497e-09 4.6107e-10 0.5965 0.77333
side 1 3.4740e-10 3.4738e-10 0.4494 0.51945
ind:side 9 6.9569e-09 7.7299e-10 1.4170 0.24590
replicate 20 1.0910e-08 5.4549e-10
$ANOVA.Shape
df SS MS Goodall.F P.param
ind 288 0.104888 0.00036419 2.69010 0.00001
side 32 0.003221 0.00010065 0.74346 0.84331
ind:side 288 0.038990 0.00013538 1.04068 0.34061
ind:side:replicate 640 0.083259 0.00013009
Function
returns
the
ANOVA
table
for
analysis
of
symmetry
and
a
graph
showing
the
shape
deformations
relating
to
the
symmetric
and
asymmetric
components
of
shape.
When
verbose=TRUE,
the
function
returns
the
symmetric
component
of
shape
variation
($symm.shape)
and
the
asymmetric
component
of
shape
variation
($asymm.shape),
to
be
used
in
subsequent
analyses
like
Procrustes
coordinates.
30
Example
of
object
symmetry:
> data(scallops)
> bilat.symmetry(scallops$coorddata, ind=scallops$ind, object.sym=TRUE,
land.pairs=scallops$land.pairs)
df SS MS Goodall.F P.param
ind 276 0.032015 1.1600e-04 8.837 1e-05
side 62 0.014419 2.3256e-04 17.717 1e-05
ind:side 248 0.003255 1.3126e-05
31
Section
3b:
Data
Analysis
After
the
data
have
been
superimposed
with
gpagen()
or
bilat.symmetry(),
the
Procrustes
coordinates
can
be
used
in
many
statistical
analyses
(this
section),
ordination
methods
and
visualization
methods
(Section
4).
Figure
3
Overview
of
the
analysis
(blue)
and
visualization
(green)
functions
in
geomorph.
Protip!
Throughout
the
analysis
functions,
one
will
see
the
option
verbose=TRUE/FALSE.
This
is
an
option
to
limit
the
amount
of
information
returned.
FALSE
is
default,
and
the
basic
results
are
returned,
usually
the
test
statistic
and
P-‐value.
When
TRUE,
the
function
will
also
return
new
datasets,
and
shape
deformation
coordinates
that
can
be
used
in
other
functions.
Look
out
for
this
option
in
many
of
the
functions.
Several
functions
have
the
option
“mesh=”,
which
is
there
for
3D
data
users
that
wish
to
view
the
shape
deformations
as
a
warped
surface
mesh.
Further
details
in
warpRefMesh().
32
3.3 Covariation
methods:
Procrustes
ANOVA/regression
for
shape
data
(procD.lm)
Function
performs
Procrustes
ANOVA
with
permutation
procedures
to
assess
statistical
hypotheses
describing
patterns
of
shape
variation
and
covariation
for
a
set
of
Procrustes-‐aligned
coordinates.
For
a
phylogenetically
informed
Procrustes
ANOVA,
use
procD.pgls()
in
3.12.
Function:
procD.lm(f1, iter = 999, RRPP = FALSE, int.first = FALSE, verbose = FALSE)
Arguments:
f1
A
formula
for
the
linear
model
(e.g.,
y~x1+x2)
iter
Number
of
iterations
for
significance
testing
RRPP
A
logical
value
indicating
whether
residual
randomization
should
be
used
for
significance
testing
int.first
A
logical
value
to
indicate
if
interactions
of
first
main
effects
should
precede
subsequent
main
effects
verbose
A
logical
value
specifying
whether
additional
output
should
be
displayed
For
several
reasons,
Procrustes
ANOVA
is
particularly
useful
for
shape
data.
First,
covariance
matrices
from
GPA-‐aligned
Procrustes
coordinates
are
singular,
and
thus
standard
approaches
such
as
MANOVA
cannot
be
accomplished
unless
generalized
inverses
are
utilized.
This
problem
is
accentuated
when
using
sliding
semilandmarks.
Additionally,
geometric
morphometric
datasets
often
have
more
variables
than
specimens
(the
'small
N
large
P'
problem).
In
these
cases,
distance-‐based
procedures
can
still
be
utilized
to
assess
statistical
hypotheses,
whereas
standard
linear
models
cannot.
The
function
quantifies
the
relative
amount
of
shape
variation
attributable
to
one
or
more
factors
in
a
linear
model
and
assesses
this
variation
via
permutation.
Data
input
is
specified
by
a
formula
(e.g.,
y~X),
where
'y'
specifies
the
response
variables
(shape
data),
and
'X'
contains
one
or
more
independent
variables
(discrete
or
continuous).
More
details
about
the
input
of
f1 and
the
option
int.first
can
be
found
in
the
Statistical
Designs
section
on
11).
The
response
variable
(y)
can
either
be
a
3D
array
of
shape
data
or
a
2D
array
of
shape
data
or
other
continuous,
multivariate
data.
The
names
specified
for
the
independent
(x)
variables
in
the
formula
represent
one
or
more
vectors
containing
continuous
data
or
factors.
It
is
assumed
that
the
order
of
the
specimens
in
the
shape
matrix
matches
the
order
of
values
in
the
independent
variables.
The
function
performs
statistical
assessment
of
the
terms
in
the
model
using
Procrustes
distances
among
specimens,
rather
than
explained
covariance
matrices
among
variables.
With
this
approach,
the
sum-‐of-‐squared
Procrustes
distances
are
used
as
a
measure
of
SS
(see
Goodall
1991).
The
observed
SS
are
evaluated
through
permutation.
In
morphometrics
this
approach
is
known
as
a
Procrustes
ANOVA
(Goodall
1991),
which
is
equivalent
to
distance-‐based
ANOVA
designs
(Anderson
2001).
Two
possible
resampling
procedures
(RRPP)
are
provided
(details
of
which
are
given
in
the
Permutation
Procedures
section
on
page
11).
Effect-‐sizes
(Z-‐scores)
are
computed
as
standard
deviates
of
the
sampling
distributions
generated,
which
might
be
more
intuitive
for
P-‐values
than
F-‐values
(see
Collyer
et
al.
2014).
In
the
case
that
multiple
factor
or
factor-‐covariate
interactions
are
used
in
the
model
formula,
one
can
specify
whether
all
main
effects
should
be
added
to
the
model
first,
or
interactions
should
precede
subsequent
main
effects
(i.e.,
Y ~ a + b + c + a:b + ...,
or
Y ~ a + b + a:b + c + ...,
respectively.)
33
Example
of
a
allometric
regression,
y~x(continuous)
:
> data(ratland)
> rat.gpa<-gpagen(ratland) #GPA-alignment
> procD.lm(two.d.array(rat.gpa$coords)~rat.gpa$Csize,iter=99)
[1] "No specimen names in response matrix. Assuming specimens in same order."
df SS MS Rsq F Z P.value
plethodon$species 1 0.029258 0.029258 0.14856 14.948 4.0848 0.01
plethodon$site 1 0.064375 0.064375 0.32688 32.889 7.4997 0.01
plethodon$species:plethodon$site 1 0.030885 0.030885 0.15682 15.779 4.5809 0.01
Residuals 37 0.072422
Total 39 0.196940
Visualization
of
the
shape
changes
can
be
done
with
plotRefToTarget().
What
next?
If
the
interaction
between
your
covariate
and
groups
is
not
significant,
meaning
groups
have
a
common
shape-‐covariate
slope,
you
can
use
a
advanced.procD.lm
with
a
formula
such
as
shape
~ group, ~covariate to
determine
which
least
squares
(LS)
shape
means
are
different
among
groups.
If
the
interaction
between
your
covariate
and
groups
is
significant,
you
can
use
a advanced.procD.lm
with
a
formula
such
as
shape ~ group, ~covariate
to
determine
which
groups
have
different
shape-‐
covariate
slopes.
34
3.4 Covariation
methods:
Procrustes
ANOVA
and
pairwise
tests
for
shape
data,
using
complex
linear
models
(advanced.procD.lm)
Function
quantifies
the
relative
amount
of
shape
variation
explained
by
a
suite
of
factors
and
covariates
in
a
"full"
model,
after
accounting
for
variation
in
a
"reduced"
model.
Inputs
are
formulae
for
full
and
reduced
models
(order
is
not
important),
plus
indication
if
means
or
slopes
are
to
be
compared
among
groups,
with
appropriate
formulae
to
define
how
they
should
be
compared.
Function:
advanced.procD.lm(f1, f2, groups = NULL, slope = NULL, angle.type = c("r",
"deg", "rad"), iter = 999, verbose = FALSE)
Arguments:
f1
A
formula
for
the
linear
model
(e.g.,
y~x1+x2)
f2
A
formula
for
another
linear
model
(e.g.,
~ x1 + x2 + x3 + a*b)
(f1
and
f2
should
be
nested)
groups
A
formula
for
grouping
factors
(e.g.,
~a, or ~a*b)
slope
A
formula
with
one
covariate
(e.g.,
~x3)
angle.type
A
value
specifying
whether
differences
between
slopes
should
be
represented
by
vector
correlations
(r),
radians
(rad)
or
degrees
(deg)
iter
Number
of
iterations
for
significance
testing
verbose
A
logical
value
specifying
whether
additional
output
should
be
displayed
The
function
performs
statistical
assessment
of
the
terms
in
the
model
using
Procrustes
distances
among
specimens,
rather
than
explained
covariance
matrices
among
variables.
With
this
approach,
the
sum-‐of-‐squared
Procrustes
distances
are
used
as
a
measure
of
SS
(see
Goodall
1991).
The
SS
between
models
is
evaluated
through
permutation.
In
morphometrics
this
approach
is
known
as
a
Procrustes
ANOVA
(Goodall
1991),
which
is
equivalent
to
distance-‐based
ANOVA
designs
(Anderson
2001).
Unlike
procD.lm(),
this
function
is
strictly
for
comparison
of
two
nested
models.
The
function
will
readily
accept
non-‐nested
models,
but
the
results
will
not
be
meaningful.
(Use
of
procD.lm()
will
be
more
suitable
in
most
cases).
A
residual
randomization
permutation
procedure
(RRPP)
is
utilized
for
reduced
model
residuals
to
evalute
the
SS
between
models
(Collyer
et
al.
2014).
Effect-‐sizes
(Z-‐scores)
are
computed
as
standard
deviates
of
the
SS
sampling
distributions
generated,
which
might
be
more
intuitive
for
P-‐values
than
F-‐values
(see
Collyer
et
al.
2014).
The
response
variable
(y)
can
either
be
a
3D
array
of
shape
data
or
a
2D
array
of
shape
data
or
other
continuous,
multivariate
data.
Pairwise
tests
are
only
performed
if
formulae
are
provided
to
compute
such
results.
35
# Example of a nested model comparison (as with ANOVA with RRPP)
> advanced.procD.lm(Y ~ log(CS) + sp, ~ log(CS)*sp*st, iter=19)
ANOVA with RRPP
df SSE SS F Z P
log(CS)+sp 37 0.161167
log(CS)+sp+st+log(CS):sp+log(CS):st+sp:st+log(CS):sp:st 32 0.061718 0.099449 10.312 3.1775 0.05
df SSE SS F Z P
st+sp 37 0.103307
st+sp+st:sp 36 0.072422 0.030885 15.352 4.0966 0.05
$Means.dist
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 0.00000000 0.02432519 0.09566672 0.1013670
Allo:Teyah 0.02432519 0.00000000 0.09193082 0.0994980
Symp:Jord 0.09566672 0.09193082 0.00000000 0.1069432
Symp:Teyah 0.10136696 0.09949800 0.10694324 0.0000000
$Prob.Means.dist
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 1.00 1.00 0.05 0.75
Allo:Teyah 1.00 1.00 0.60 0.05
Symp:Jord 0.05 0.60 1.00 0.05
Symp:Teyah 0.75 0.05 0.05 1.00
df SSE SS F Z P
log(CS)+st+sp 36 0.098490
log(CS)+st+sp+st:sp 35 0.068671 0.029819 15.198 4.0286 0.05
$LS.Means.dist
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 0.00000000 0.02473040 0.09396152 0.10148562
Allo:Teyah 0.02473040 0.00000000 0.08999162 0.09949284
Symp:Jord 0.09396152 0.08999162 0.00000000 0.10547891
Symp:Teyah 0.10148562 0.09949284 0.10547891 0.00000000
$Prob.Means.dist
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 1.0 1.00 0.20 0.60
Allo:Teyah 1.0 1.00 0.75 0.05
Symp:Jord 0.2 0.75 1.00 0.05
Symp:Teyah 0.6 0.05 0.05 1.00
$Slopes.dist
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 0.0000000 0.1780151 0.2188238 0.1231082
Allo:Teyah 0.1780151 0.0000000 0.2718850 0.1390140
36
Symp:Jord 0.2188238 0.2718850 0.0000000 0.2354029
Symp:Teyah 0.1231082 0.1390140 0.2354029 0.0000000
$Prob.Slopes.dist
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 1.00 0.25 0.65 0.50
Allo:Teyah 0.25 1.00 0.35 0.55
Symp:Jord 0.65 0.35 1.00 0.35
Symp:Teyah 0.50 0.55 0.35 1.00
$Slopes.correlation
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 1.000000000 -0.006345334 0.01344439 0.1577696
Allo:Teyah -0.006345334 1.000000000 -0.28849007 0.3397718
Symp:Jord 0.013444387 -0.288490065 1.00000000 -0.3441474
Symp:Teyah 0.157769562 0.339771753 -0.34414737 1.0000000
$Prob.Slopes.cor
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 1.0 0.10 0.40 0.20
Allo:Teyah 0.1 1.00 0.15 0.55
Symp:Jord 0.4 0.15 1.00 0.10
Symp:Teyah 0.2 0.55 0.10 1.00
df SSE SS F Z P
log(CS)+st+sp+st:sp 35 0.068671
log(CS)+st+sp+log(CS):st+log(CS):sp+st:sp+log(CS):st:sp 32 0.061718 0.0069531 1.2017 1.1762 0.25
$LS.Means.dist
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 0.00000000 0.02473040 0.09396152 0.10148562
Allo:Teyah 0.02473040 0.00000000 0.08999162 0.09949284
Symp:Jord 0.09396152 0.08999162 0.00000000 0.10547891
Symp:Teyah 0.10148562 0.09949284 0.10547891 0.00000000
$Prob.Means.dist
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 1.00 0.85 0.65 0.50
Allo:Teyah 0.85 1.00 0.70 0.55
Symp:Jord 0.65 0.70 1.00 0.45
Symp:Teyah 0.50 0.55 0.45 1.00
$Slopes.dist
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 0.0000000 0.1780151 0.2188238 0.1231082
Allo:Teyah 0.1780151 0.0000000 0.2718850 0.1390140
Symp:Jord 0.2188238 0.2718850 0.0000000 0.2354029
Symp:Teyah 0.1231082 0.1390140 0.2354029 0.0000000
$Prob.Slopes.dist
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 1.00 0.05 0.55 0.20
Allo:Teyah 0.05 1.00 0.25 0.25
Symp:Jord 0.55 0.25 1.00 0.30
Symp:Teyah 0.20 0.25 0.30 1.00
$Slopes.angle
37
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 0.00000 90.36356 89.22967 80.92254
Allo:Teyah 90.36356 0.00000 106.76758 70.13703
Symp:Jord 89.22967 106.76758 0.00000 110.12976
Symp:Teyah 80.92254 70.13703 110.12976 0.00000
$Prob.Slopes.angle
Allo:Jord Allo:Teyah Symp:Jord Symp:Teyah
Allo:Jord 1.00 0.25 0.30 0.15
Allo:Teyah 0.25 1.00 0.10 0.55
Symp:Jord 0.30 0.10 1.00 0.05
Symp:Teyah 0.15 0.55 0.05 1.00
df SSE SS F Z P
log(CS)+st+sp+st:sp 35 0.068671
log(CS)+st+sp+log(CS):st+log(CS):sp+st:sp+log(CS):st:sp 32 0.061718 0.0069531 1.2017 1.3022 0.15
$LS.Means.dist
Jord Teyah
Jord 0.00000000 0.05269568
Teyah 0.05269568 0.00000000
$Prob.Means.dist
Jord Teyah
Jord 1.0 0.6
Teyah 0.6 1.0
$Slopes.dist
Jord Teyah
Jord 0.0000000 0.1787995
Teyah 0.1787995 0.0000000
$Prob.Slopes.dist
Jord Teyah
Jord 1.00 0.05
Teyah 0.05 1.00
$Slopes.angle
Jord Teyah
Jord 0.00000 81.91376
Teyah 81.91376 0.00000
$Prob.Slopes.angle
Jord Teyah
Jord 1.00 0.05
Teyah 0.05 1.00
38
Function
returns
a
list
containing
the
ANOVA
table
of
statistical
results
for
model
comparison:
error
df
(for
each
model),
SS,
MS,
F
ratio,
Z,
and
Prand
($anova.table),
as
well
as
the
distances
and
probabilities
of
the
tests
for
groups
and
slope
covariates.
The
following
may
also
be
returned.
$Means.dist
Pairwise
distance
between
means,
if
applicable
$LS.Means.dist
Pairwise
distance
between
LS
means,
if
applicable
$Prob.Means.dist
P-‐values
for
pairwise
distances
between
means
$Slopes.dist Pairwise
distance
between
slope
vectors
(difference
in
amount
of
shape
change),
if
applicable
$Prob.Slopes.dist
P-‐values
for
pairwise
distances
between
slopes
$Slopes.correlation
Pairwise
vector
correlations
between
slope
vectors,
if
applicable
$Prob.Slopes.cor
P-‐values
for
pairwise
correlations
between
slope
vectors
(high
correlation
less
significant)
$Slopes.angle
Angles
between
between
slope
vectors,
if
applicable
$Prob.Slopes.angle
P-‐values
for
pairwise
angles
between
slope
vectors
And
when
verbose=TRUE:
$SS.rand
Random
SS
from
RRPP
permutations
$random.mean.dist
random
pairwise
distances
between
means
from
RRPP
permutations
$random.slope.dist
random
pairwise
distances
between
slopes
from
RRPP
permutations
$random.slope.comp
random
pairwise
slope
direction
comparisons
(r
or
angle)
from
RRPP
permutations
39
3.5 Covariation
methods:
Two-‐block
partial
least
squares
analysis
for
shape
data
(two.b.pls)
Function
performs
two-‐block
partial
least
squares
analysis
to
assess
the
degree
of
association
between
to
blocks
of
Procrustes-‐aligned
coordinates
(or
other
variables).
Function:
two.b.pls(A1, A2, warpgrids = TRUE, iter = 999, verbose = FALSE)
Arguments:
A1
A
2D
array
(n
x
[p1
x
k])
or
3D
array
(p1
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
Block1
A2
A
2D
array
(n
x
[p2
x
k])
or
3D
array
(p2
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
Block2
iter
Number
of
iterations
for
significance
testing
warpgrids
A
logical
value
indicating
whether
deformation
grids
for
shapes
along
PC1
should
be
displayed
(only
relevant
if
data
for
A1
or
A2
[or
both]
were
input
as
3D
array)
verbose
A
logical
value
indicating
whether
the
output
is
basic
or
verbose
(see
Value
below)
The
function
quantifies
the
degree
of
association
between
two
blocks
of
shape
data
as
defined
by
landmark
coordinates
(or
one
block
of
shape
data
and
a
block
of
continuous,
multivariate
data)
using
partial
least
squares
(see
Rohlf
and
Corti
2000).
A
plot
of
PLS
scores
from
Block1
versus
Block2
is
provided
for
the
first
set
of
PLS
axes.
Thin-‐plate
spline
deformation
grids
along
these
axes
are
also
shown
(if
data
were
input
as
a
3D
array
and
warpgrids=TRUE).
If
verbose = TRUE,
the
function
also
returns
a
list
containing
the
PLS
scores
for
the
40
first
block
of
landmarks
($Xscores)
and
for
the
second
block
of
landmarks
($Yscores).
These
can
be
used
to
make
further
plots
(plot())
and
shape
deformations
(plotRefToTarget()).
Protip!
Function
can
be
used
in
many
combinations,
and
is
not
exclusively
for
shape
data.
For
example,
one
block
as
shape
data
for
a
structure
and
the
other
block
shape
for
another
structure
(but
also
see
morphol.integr()),
or
one
block
as
multivariate
continuous
data
(e.g.,
Precipitation)
and
other
block
for
shape
data
or
two
blocks
of
non-‐shape,
multivariate
continuous
data.
For
single
variables,
if
Y~x
or
y~X,
two-b.pls
becomes
multivariate
(major-‐axis)
regression
or
multiple
regression,
respectively.
If
y~x,
two-b.pls
is
simply
a
correlation
analysis.
3.6 Morphological
Integration
methods:
Quantify
morphological
integration
between
two
modules
(morphol.integr)
Function
quantifies
the
degree
of
morphological
integration
between
two
modules
of
Procrustes-‐
aligned
coordinates.
The
function
may
be
used
to
assess
the
degree
of
morphological
integration
between
two
separate
structures
or
between
two
modules
defined
within
the
same
landmark
configuration.
Function:
morphol.integr(A1, A2, method = c("PLS", "RV"), warpgrids = TRUE,
iter = 999, verbose = FALSE)
Arguments:
A1
A
2D
array
(n
x
[p1
x
k])
or
3D
array
(p1
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
the
first
module
A2
A
2D
array
(n
x
[p2
x
k])
or
3D
array
(p2
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
the
second
module
method
Method
to
estimate
morphological
integration;
see
below
for
details
warpgrids
A
logical
value
indicating
whether
deformation
grids
for
shapes
along
PLS1
should
be
displayed
(only
relevant
if
data
for
A1
or
A2
[or
both]
were
input
as
3D
array)
iter
Number
of
iterations
for
significance
testing
verbose
A
logical
value
indicating
whether
the
output
is
basic
or
verbose
(method="PLS"
only)
(see
Value
below)
Two
analytical
approaches
are
currently
implemented
to
assess
the
degree
of
morphological
integration,
method="PLS"
and
method="RV".
method="PLS"
(default)
the
function
estimates
the
degree
of
morphological
integration
using
two-‐
block
partial
least
squares,
or
PLS.
When
used
with
landmark
data,
this
analysis
is
referred
to
as
singular
warps
analysis
(Bookstein
et
al.
2003).
When
method="PLS",
the
scores
along
the
X
&
Y
PLS
axes
are
also
returned,
as
is
a
plot
of
PLS
scores
from
Block1
versus
Block2
along
the
first
set
of
PLS
axes.
Thin-‐plate
spline
deformation
grids
along
these
axes
are
also
shown
(if
data
were
input
as
a
3D
array).
Note:
deformation
grids
are
displayed
for
each
block
of
landmarks
separately.
> data(plethodon)
> Y.gpa<-gpagen(plethodon$land) #GPA-alignment
> morphol.integr(Y.gpa$coords[1:5,,],Y.gpa$coords[6:12,,],method="PLS",iter=99)
[1] "No specimen names in data matrix 1. Assuming specimens in same order."
[1] "No specimen names in data matrix 2. Assuming specimens in same order."
$PLS.corr
[1] 0.9108678
$pvalue
[1] 0.01
41
A
plot
of
PLS
scores
from
Block1
versus
Block2
is
provided
for
the
first
set
of
PLS
axes.
Thin-‐plate
spline
deformation
grids
along
these
axes
are
also
shown
(if
data
were
input
as
a
3D
array
and
warpgrids=TRUE).
If
verbose=TRUE,
the
function
also
returns
a
list
containing
the
PLS
scores
for
the
first
block
of
landmarks
($Xscores)
and
for
the
second
block
of
landmarks
($Yscores).
These
can
be
used
to
make
further
plots
(plot())
and
shape
deformations
(plotRefToTarget()).
Protip!
If
the
two
blocks
of
landmarks
are
derived
from
a
single
structure
(i.e.,
a
single
landmark
configuration),
one
can
plot
the
overall
deformation
along
PLS1
as
follows,
> res<-morphol.integr(Y.gpa$coords[1:5,,],Y.gpa$coords[6:12,,],
method="PLS",iter=99, verbose=TRUE)
> ref<-mshape(Y.gpa$coords) #overall reference
> plotRefToTarget(ref,Y.gpa$coords[,,which.min(res$x.scores)],method="TPS") #Min
along PLS1
> plotRefToTarget(ref,Y.gpa$coords[,,which.max(res$x.scores)],method="TPS") #Max
along PLS1
method="RV"
the
function
estimates
the
degree
of
morphological
integration
using
the
RV
coefficient
(Klingenberg
2009).
Significance
testing
for
both
approaches
is
found
by
permuting
the
objects
in
one
data
matrix
relative
to
those
in
the
other.
A
histogram
of
coefficients
obtained
via
resampling
is
presented,
with
the
observed
value
designated
by
an
arrow
in
the
plot.
> data(plethodon)
> Y.gpa<-gpagen(plethodon$land) #GPA-alignment
> morphol.integr(Y.gpa$coords[1:5,,],Y.gpa$coords[6:12,,],method="RV",iter=99)
[1] "No specimen names in data matrix 1. Assuming specimens in same order."
42
[1] "No specimen names in data matrix 2. Assuming specimens in same order."
$RV
[1] 0.6214977
$pvalue
[1] 0.01
If
evaluating
an
a
priori
hypothesis
of
modularity
within
a
structure
is
of
interest,
one
may
use
the
average
RV
coefficient
as
implemented
in
the
function
compare.modular.partitions().
3.7 Morphological
Integration
methods:
Quantify
global
integration
relative
to
self-‐similarity
(globalIntegration)
Function
quantifies
the
overall
level
of
morphological
integration
for
a
set
of
Procrustes-‐aligned
coordinates
Function:
globalIntegration (A)
Arguments:
A
A
3D
array
(p
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
all
specimens
The
function
quantifies
the
overall
level
of
morphological
integration
for
a
set
of
Procrustes
coordinates.
Based
on
the
set
of
aligned
specimens,
the
function
estimates
the
set
of
bending
energies
at
various
spatial
scales,
and
plots
the
log
of
the
variance
of
the
partial
warps
versus
the
log
of
their
corresponding
bending
energies
(Bookstein
2015).
For
slope
of
a
regression
of
these
data
provides
information
regarding
the
degree
of
overall
morphological
integration
(or
lack
thereof).
A
slope
of
negative
one
corresponds
to
self-‐similarity,
implying
that
patterns
of
shape
variation
are
similar
across
spatial
scales.
Steeper
slopes
(i.e.,
those
larger
than
-‐1.0)
correspond
to
data
that
are
globally
integrated,
while
shallower
slopes
to
data
that
are
'disintegrated
(see
Bookstein
2015).
Isotropic
data
will
have
an
expected
slope
of
zero.
For
example:
> data(plethodon)
> Y.gpa<-gpagen(plethodon$land) #GPA-alignment
> globalIntegration(Y.gpa$coords)
BEval
-0.6369207
43
3.8 Morphological
Integration
methods:
Compare
modular
signal
to
alternative
landmark
subsets
(compare.modular.partitions)
Function
quantifies
the
degree
of
morphological
integration
between
two
or
more
modules
of
Procrustes-‐aligned
landmark
coordinates
defined
a
priori
and
compares
this
to
patterns
found
by
randomly
assigning
landmarks
into
subsets.
Only
modules
within
the
same
configuration
should
be
tested.
Function:
compare.modular.partitions(A, landgroups, iter = 999)
Arguments:
A
A
3D
array
(p
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
all
specimens,
or
a
matrix
(n
x
variables)
landgroups
A
list
of
which
landmarks
belong
in
which
partition
(e.g.,
A,A,A,B,B,B,C,C,C)
iter
Number
of
iterations
for
significance
testing
The
function
quantifies
the
degree
of
modularity
in
two
or
more
hypothesized
modules
of
shape
data
as
defined
by
landmark
coordinates,
and
compares
this
to
the
degree
of
modular
signal
found
in
random
assignment
of
landmarks
to
modules.
The
degree
of
modularity
is
quantified
using
the
RV
coefficient
(Klingenberg
2009).
If
more
than
two
modules
are
defined,
the
average
RV
coefficient
is
utilized
(see
Klingenberg
2009).
The
RV
coefficient
for
the
observed
modular
hypothesis
is
then
compared
to
a
distribution
of
values
obtained
by
randomly
assigning
landmarks
into
subsets,
with
the
restriction
that
the
number
of
landmarks
in
each
subset
is
identical
to
that
observed
in
each
of
the
original
partitions.
A
significant
modular
signal
is
found
when
the
observed
RV
coefficient
is
small
relative
to
this
distribution
(see
Klingenberg
2009).
A
histogram
of
coefficients
obtained
via
resampling
is
presented,
with
the
observed
value
designated
by
an
arrow
in
the
plot.
44
To
use
this
method
with
other
data
(i.e.,
a
set
of
length
measurements),
the
input
A
should
be
a
matrix
of
n
rows
of
specimens
and
variables
arranged
in
columns.
In
this
case,
the
partition.gp
input
should
have
each
variable
assigned
to
a
partition.
The
landgroups
argument
can
be
made
by
hand,
using
c(),
or
there
is
a
graphical
assisted
function
define.modules().
2D
Example
where
the
modularity
hypothesis
is
the
cranium
versus
the
mandible,
> data(plethodon)
> Y.gpa<-gpagen(plethodon$land) #GPA-alignment
> #landmarks on the skull and mandible assigned to partitions
> land.gps <- c("A","A","A","A","A","B","B","B","B","B","B","B")
> # OR
> land.gps <- define.modules(plethodon$land[,,1], nmodules=2)
Select landmarks in module 1
Press esc when finished
[1] "A" "A" "A" "A" "A" "B" "B" "B" "B" "B" "B" "B"
> compare.modular.partitions(Y.gpa$coords,land.gps,iter=99)
> #Result implies that the skull and mandible are not independent modules
45
define.modules
Function:
define.modules(spec, nmodules)
Arguments:
spec
Name
of
specimen,
as
an
object
matrix
containing
2D
or
3D
landmark
coordinates
nmodules
Number
of
modules
to
be
defined
Function
takes
a
matrix
of
two-‐dimensional
digitized
landmark
coordinates
and
allows
user
assign
landmarks
to
each
module.
The
output
is
a
list
of
which
landmarks
belong
in
which
partition,
to
be
used
by
compare.modular.partitions() option landgroups.
Choosing
which
landmarks
will
be
included
in
each
module
involves
landmark
selection
using
a
mouse
in
the
rgl
plot
window.
The
user
is
prompted
to
select
one
or
more
landmarks.
To
do
so,
use
the
RIGHT
mouse
button
(or
command
+
LEFT
button
for
Mac
users),
draw
a
rectangle
around
one
or
more
landmarks
to
select.
Selected
landmarks
will
be
colored
yellow.
Then
type
into
the
console
a
letter
(e.g.
1,
2,
3...)
to
assign
selected
landmark(s)
to
this
module.
Repeat
until
all
landmarks
are
assigned
to
modules.
46
3.9 Phylogenetic
Comparative
methods:
Assessing
phylogenetic
signal
in
morphometric
data
(physignal)
Function
calculates
the
degree
of
phylogenetic
signal
from
a
set
of
Procrustes-‐aligned
specimens.
Function:
physignal(phy, A, iter = 999, ShowPlot = TRUE, c("Kmult", "SSC"))
Arguments:
phy
A
phylogenetic
tree
of
class
'phylo'
A
A
2D
array
(n
x
[p
x
k])
or
3D
array
(p
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
a
set
of
specimens
iter
Number
of
iterations
for
significance
testing
ShowPlot
A
logical
value
indicating
whether
or
not
he
plot
should
be
returned
method
Method
for
estimating
phylogenetic
signal
(Kmult
or
SSC)
The
function
estimates
the
degree
of
phylogenetic
signal
present
in
shape
data
for
a
given
phylogeny.
Two
approaches
may
be
used
to
quantify
phylogenetic
signal.
First,
method = "Kmult",
a
multivariate
version
of
the
K-‐statistic
may
be
utilized
(Kmult:
Adams
2014a).
This
value
evaluates
the
degree
of
phylogenetic
signal
in
a
dataset
relative
to
what
is
expected
under
a
Brownian
motion
model
of
evolution.
For
geometric
morphometric
data,
the
approach
is
a
mathematical
generalization
of
the
Kappa
statistic(Blomberg
et
al.
2003)
appropriate
for
highly
multivariate
data
(see
Adams
2014a).
The
second
approach,
method = "SSC"
,
estimates
the
phylogenetic
signal
as
the
sum
of
squared
changes
(SSC)
in
shape
along
all
branches
of
the
phylogeny
(Klingenberg
and
Gidaszewski
2010).
Significance
testing
is
found
by
permuting
the
shape
data
among
the
tips
of
the
phylogeny.
Note
that
the
method
can
be
slow
as
ancestral
states
must
be
estimated
for
every
iteration.
A
plot
of
the
specimens
in
tangent
space
with
the
phylogeny
superimposed
is
included.
The
tree
must
have
number
of
tips
equal
to
number
of
taxa
in
the
data
matrix
(e.g.,
ape
package
function
drop.tip()).
And,
tip
labels
of
the
tree
MUST
be
exactly
the
same
as
the
taxa
names
in
the
landmark
data
matrix
(check
using
match()).
To
learn
more
about
phylogenetic
trees
in
R,
look
at
these
resources:
http://www.r-‐phylo.org/wiki/
and
http://bodegaphylo.wikispot.org/Phylogenetics_and_Comparative_Methods_in_R
> data(plethspecies)
> Y.gpa<-gpagen(plethspecies$land) #GPA-alignment
> plethspecies$phy # look at the structure of the tree (class phylo)
Phylogenetic tree with 9 tips and 8 internal nodes.
Tip labels:
P_serratus, P_cinereus, P_shenandoah, P_hoffmani, P_virginia, P_nettingi, ...
47
Example
using
method = "Kmult",
> physignal(plethspecies$phy,Y.gpa$coords,iter=99, method = "Kmult")
$phy.signal
[,1]
[1,] 0.957254
$pvalue
[,1]
[1,] 0.02
Example
using
method = “SSC” ,
> physignal(plethspecies$phy,Y.gpa$coords,iter=99, method = "SSC")
$phy.signal
[1] 0.002235759
$pvalue
[1] 0.01
This
function
also
calls
4.4 plotGMPhyloMorphoSpace() and
plots
the
phylomorphospace.
48
This
function
can
be
used
with
univariate
data
(i.e.,
centroid
size)
if
imported
as
matrix
with
row
names
giving
the
taxa
names.
># make matrix Csize with names
> Csize <- matrix(Y.gpa$Csize, dimnames=list(names(Y.gpa$Csize)))
> physignal(plethspecies$phy,Csize,iter=99, method = "Kmult")
$phy.signal
[,1]
[1,] 0.7097642
$pvalue
[,1]
[1,] 0.49
> physignal(plethspecies$phy,Csize,iter=99, method = "SSC")
$phy.signal
[1] 1.762033e-07
$pvalue
[1] 0.3
49
$`PLS Correlation`
[1] 0.9338463
$pvalue
[,1]
[1,] 0.02777778
A
plot
of
PLS
scores
from
Block1
versus
Block2
is
provided
for
the
first
set
of
PLS
axes.
Thin-‐plate
spline
deformation
grids
along
these
axes
are
also
shown
(if
data
were
input
as
a
3D
array
and
warpgrids=TRUE).
If
verbose=TRUE,
the
function
also
returns
a
list
containing
the
PLS
scores
for
the
first
block
of
landmarks
($Xscores)
and
for
the
second
block
of
landmarks
($Yscores).
These
can
be
used
to
make
further
plots
(plot())
and
shape
deformations
(plotRefToTarget()).
3.11 Phylogenetic
Comparative
methods:
Comparing
rates
of
shape
evolution
on
phylogenies
(compare.evol.rates)
Function
calculates
rates
of
shape
evolution
for
two
or
more
groups
of
species
on
a
phylogeny
from
a
set
of
Procrustes-‐aligned
specimens.
Function:
compare.evol.rates(phy, A, gp, ShowPlot = TRUE, iter = 999)
Arguments:
phy
A
phylogenetic
tree
of
class
'phylo'
A
A
matrix
(n
x
[p
x
k])
or
3D
array
(p
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
a
set
of
specimens
gp
A
factor
array
designating
group
membership
ShowPlot
A
logical
value
indicating
whether
or
not
the
plot
should
be
returned
iter
Number
of
iterations
for
significance
testing
The
function
compares
rates
of
morphological
evolution
for
two
or
more
groups
of
species
on
a
phylogeny,
under
a
Brownian
motion
model
of
evolution.
The
approach
is
based
on
the
distances
between
species
in
morphospace
after
phylogenetic
transformation
(Adams
2014c).
From
the
data
the
rate
of
shape
evolution
for
each
group
is
calculated,
and
a
ratio
of
rates
is
obtained.
If
three
or
more
groups
of
species
are
used,
the
ratio
of
the
maximum
to
minimum
rate
is
used
as
a
test
statistic
(see
Adams
2014c).
Significance
testing
is
accomplished
by
phylogenetic
simulation
in
which
tips
data
are
obtained
under
Brownian
motion
using
a
single
evolutionary
rate
for
all
species
on
the
phylogeny.
If
three
or
more
groups
of
species
are
used,
pairwise
P-‐values
are
also
returned.
A
histogram
of
evolutionary
rate
ratios
obtained
via
phylogenetic
simulation
is
presented,
with
the
observed
value
designated
by
an
arrow
in
the
plot.
The
function
can
be
used
to
obtain
a
rate
for
the
whole
dataset
of
species
by
using
a
dummy
group
factor
assigning
all
species
to
one
group.
50
Example,
comparing
endangered
versus
not
endangered
species
of
Plethodon,
> data(plethspecies)
> Y.gpa<-gpagen(plethspecies$land) #GPA-alignment
> gp.end<-factor(c(0,0,1,0,0,1,1,0,0)) #endangered species vs. rest
> names(gp.end)<-plethspecies$phy$tip
> compare.evol.rates(plethspecies$phy,Y.gpa$coords,gp=gp.end,iter=49)
$sigma.d
[1] 2.297943e-06
$sigmad.all
0 1
1.796579e-06 3.300672e-06
$sigmad.ratio
[1] 1.837199
$pvalue
[1] 0.02
This
function
can
be
used
with
univariate
data
(i.e.,
centroid
size)
if
imported
as
matrix
with
row
names
giving
the
taxa
names,
> Csize <- matrix(Y.gpa$Csize, dimnames=list(names(Y.gpa$Csize))) # make matrix
Csize with names
> compare.evol.rates(plethspecies$phy,Csize,gp=gp.end,iter=49)
$sigma.d
[1] 3.013353e-09
$sigmad.all
0 1
1.776216e-09 5.487627e-09
$sigmad.ratio
[1] 3.089505
$pvalue
[1] 0.38
3.12 Phylogenetic
Comparative
methods:
Phylogenetic
ANOVA/regression
for
shape
data
(procD.pgls)
Function
performs
Procrustes
ANOVA
in
a
phylogenetic
framework
and
uses
permutation
procedures
to
assess
statistical
hypotheses
describing
patterns
of
shape
variation
and
covariation
for
a
set
of
Procrustes-‐aligned
coordinates
Function:
procD.pgls(f1, phy, iter = 999)
Arguments:
51
f1
A
formula
for
the
linear
model
(e.g.,
y~x1+x2)
phy
A
phylogenetic
tree
of
class
‘phylo’
iter
Number
of
iterations
for
permutation
test
The
function
performs
ANOVA
and
regression
models
in
a
phylogenetic
context
under
a
Brownian
motion
model
of
evolution,
in
a
manner
that
can
accommodate
high-‐dimensional
datasets.
The
approach
is
derived
from
the
statistical
equivalency
between
parametric
methods
utilizing
covariance
matrices
and
methods
based
on
distance
matrices
(Adams
2014b).
Data
input
is
specified
by
a
formula
(e.g.,
y~X),
where
'y'
specifies
the
response
variables
(shape
data),
and
'X'
contains
one
or
more
independent
variables
(discrete
or
continuous).
The
response
variable
(y)
can
either
be
a
3D
array
of
shape
data
or
a
2D
array
of
shape
data
or
other
continuous,
multivariate
data.
The
user
must
also
specify
a
phylogeny
describing
the
evolutionary
relationships
among
species
(of
class
phylo).
Note
that
the
specimen
labels
for
both
x
and
y
must
match
the
labels
on
the
tips
of
the
phylogeny.
From
the
phylogeny,
a
phylogenetic
transformation
matrix
is
obtained
under
a
Brownian
motion
model,
and
used
to
transform
the
x
and
y
variables.
Next,
the
Gower-‐centered
distance
matrix
is
obtained
from
predicted
values
from
the
model
(y~x),
from
which
sums-‐of-‐squares,
F-‐ratios,
and
R2
are
estimated
for
each
factor
in
the
model
(see
Adams
2014b).
Data
are
then
permuted
across
the
tips
of
the
phylogeny,
and
estimates
of
statistical
values
are
obtained
for
the
permuted
data,
which
are
compared
to
the
observed
value
to
assess
significance.
> data(plethspecies)
> Y.gpa<-gpagen(plethspecies$land) #GPA-alignment
> procD.pgls(two.d.array(Y.gpa$coords)~Y.gpa$Csize,plethspecies$phy,iter=49)
df SS MS Rsq F P.val
Y.gpa$Csize 1 0.00006872 6.8718e-05 0.15103 1.2453 0.28
Residuals 7 0.00038628 5.5182e-05
Function
returns
an
ANOVA
table
of
statistical
results
for
all
factors:
df
(for
each
factor),
SS,
MS,
F
ratio,
Prand,
and
R2.
3.13 Calculate
morphological
disparity
for
one
or
more
groups
(morphol.disparity)
Function
estimates
morphological
disparity
and
performs
pairwise
comparisons
to
identify
differences
between
groups.
Function:
morphol.disparity(A, groups, iter = 999)
Arguments:
A
A
2D
array
(n
x
[p
x
k])
or
3D
array
(p
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
a
set
of
specimens
groups
A
factor
defining
groups
iter
Number
of
iterations
for
permutation
test
The
function
takes
as
input
GPA-‐aligned
shape
data
and
a
grouping
factor,
and
estimates
disparity
as
the
Procrustes
variance
for
each
group,
which
is
the
sum
of
the
diagonal
elements
of
the
group
covariance
matrix
(Zelditch
et
al.
2012).
The
group
Procrustes
variances
are
used
as
test
values,
and
these
are
then
statistically
evaluated
through
permutation,
where
the
vectors
of
residuals
are
randomized
among
groups.
The
function
can
be
used
to
obtain
disparity
for
the
whole
dataset
by
using
a
dummy
group
factor
assigning
all
specimens
to
one
group,
in
which
case
only
Procrustes
variance
is
returned.
52
> data(plethodon)
> Y.gpa<-gpagen(plethodon$land) #GPA-alignment
> morphol.disparity(Y.gpa$coords, groups=plethodon$site, iter = 99)
$Disp.obs
ProcVar
Allo 0.001981131
Symp 0.004647113
$Prob.Disp
Allo Symp
Allo 1.00 0.01
Symp 0.01 1.00
Use
plotTangentSpace()
to
view
the
morphospace
and
color
by
group.
3.14 Quantify
and
compare
shape
change
trajectories
(trajectory.analysis)
Function
estimates
attributes
of
shape
change
trajectories
or
motion
trajectories
for
a
set
of
Procrustes-‐aligned
specimens
and
compares
them
statistically.
Function:
trajectory.analysis(f1, data = NULL, estimate.traj = TRUE,
traj.pts = NULL, iter = 99)
Arguments:
f1
A
formula
for
the
linear
model
(e.g.,
y~x1+x2),
where
y
is
a
two-‐dimensional
array
of
shape
data
data
An
optional
value
specifying
a
data
frame
containing
all
data
(not
required)
estimate.traj
A
logical
value
indicating
whether
trajectories
are
estimated
from
original
data;
described
below
iter
Number
of
iterations
for
significance
testing
traj.pts
An
optional
value
specifying
the
number
of
points
in
each
trajectory
(if
estimate.traj=FALSE)
The
function
quantifies
phenotypic
shape
change
trajectories
from
a
set
of
specimens,
and
assesses
variation
in
these
parameters
via
permutation.
A
shape
change
trajectory
is
defined
by
a
sequence
of
shapes
in
tangent
space.
These
trajectories
can
be
quantified
various
attributes
(their
size,
orientation,
and
shape),
and
comparisons
of
these
attribute
enables
the
statistical
comparison
of
shape
change
trajectories
(see
Adams
and
Collyer
2007;
Collyer
and
Adams
2007;
Adams
and
Collyer
2009;
Collyer
and
Adams
2013).
Data
input
is
specified
by
a
formula
(e.g.,
Y~X),
where
'Y'
specifies
the
response
variables
(trajectory
data),
and
'X'
contains
one
or
more
independent
variables
(discrete
or
continuous).
The
response
matrix
'Y'
must
be
in
the
form
of
a
two-‐dimensional
data
matrix
of
dimension
(n
x
[p
x
k]),
rather
than
a
3D
array.
The
function
two.d.array()
can
be
used
to
obtain
a
two-‐dimensional
data
matrix
from
a
3D
array
of
landmark
coordinates.
It
is
assumed
that
the
order
of
the
specimens
'Y'
matches
the
order
of
specimens
in
'X'.
There
are
two
primary
modes
of
analysis
through
this
function.
If
"estimate.traj=TRUE"
the
function
estimates
shape
trajectories
using
the
least-‐squares
means
for
groups,
based
on
a
two-‐factor
model
(e.g.,
Y~A+B+A:B).
Under
this
implementation,
the
last
factor
in
'X'
must
be
the
interaction
term,
and
the
preceding
two
factors
must
be
the
effects
of
interest.
Covariates
may
be
included
in
'X',
and
must
precede
the
factors
of
interest
(e.g.,
Y~cov+A*B).
In
this
implementation,
'Y'
contains
a
matrix
of
53
landmark
coordinates.
It
is
assumed
that
the
landmarks
have
previously
been
aligned
using
Generalized
Procrustes
Analysis
(GPA).
If
"estimate.traj=FALSE"
the
trajectories
are
assembled
directly
from
the
set
of
shapes
provided
in
'Y'.
With
this
implementation,
the
user
must
specify
the
number
of
shapes
that
comprise
each
trajectory.
This
approach
is
useful
when
the
set
of
shapes
forming
each
trajectory
have
been
quantified
directly
(e.g.,
when
motion
paths
are
compared:
see
Adams
and
Cerney
2007).
With
this
implementation,
variation
in
trajectory
size,
shape,
and
orientation
are
evaluated
for
each
term
in
'X'
(see
Adams
and
Cerney
2007).
Once
the
function
has
performed
the
analysis,
it
generates
a
plot
of
the
trajectories
as
visualized
in
the
space
of
principal
components
(PC1
vs.
PC2).
The
first
point
in
each
trajectory
is
displayed
as
white,
the
last
point
is
black,
and
any
middle
points
on
the
trajectories
are
in
gray.
The
colors
of
trajectories
follow
the
order
in
which
they
are
found
in
the
dataset,
using
R's
standard
color
palette:
black,
red,
green,
blue,
cyan,
magenta,
yellow,
and
gray.
Example
to
estimate
trajectories
from
LS
means
in
2-‐factor
model
> data(plethodon)
> Y.gpa<-two.d.array(gpagen(plethodon$land)$coords)
> trajectory.analysis(Y.gpa~plethodon$species*plethodon$site,iter=15)
[1] "No specimen names in response matrix. Assuming specimens in same order."
$ProcDist.lm
df SS MS Rsq F P.val
plethodon$species 1 0.029258 0.029258 0.14856 14.544 0.0625
plethodon$site 1 0.064375 0.064375 0.32688 32.000 0.0625
plethodon$species:plethodon$site 1 0.030885 0.030885 0.15682 15.352 0.0625
Residuals 36 0.072422 0.002012
Total 39 0.196940 0.005050
$traj.size
1 2
1 0.000000000 0.003831272
2 0.003831272 0.000000000
$p.size
1 2
1 1.0000 0.5625
2 0.5625 1.0000
$traj.orient
[,1] [,2]
[1,] 0.00000 69.40048
[2,] 69.40048 0.00000
$p.orient
[,1] [,2]
[1,] 1.0000 0.0625
[2,] 0.0625 1.0000
54
Compare
motion
trajectories
> data(motionpaths)
> motionpaths #Motion paths represented by 5 time points per motion
$trajectories
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1.5547554 10.882688 2.292724 13.795449 3.189067 16.425534 5.576099 17.579038
[2,] 3.1034540 11.794735 2.445819 13.830566 3.197470 18.280553 6.432909
...
$groups
[1] 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4
Levels: 1 2 3 4
> trajectory.analysis(motionpaths$trajectories~motionpaths$groups,
estimate.traj=FALSE, traj.pts=5,iter=15)
$MANOVA.location.covariation
df SS MS Rsq F P.val
motionpaths$groups 3 6520.9 2173.63 0.98608 849.85 0.0625
Residuals 36 92.1 2.56
Total 39 6613.0 169.56
$ANOVA.Size
Df SumsOfSqs MeanSqs F.Model R2 Pr(>F)
motionpaths$groups 3 103.345 34.448 51.392 0.8107 0.0625 .
Residuals 36 24.131 0.670 0.1893
Total 39 127.475 1.0000
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
$ANOVA.Dir
Df SumsOfSqs MeanSqs F.Model R2 Pr(>F)
motionpaths$groups 3 20490.4 6830.1 90.147 0.88252 0.0625 .
Residuals 36 2727.6 75.8 0.11748
Total 39 23218.0 1.00000
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
$ANOVA.Shape
Df SumsOfSqs MeanSqs F.Model R2 Pr(>F)
motionpaths$groups 3 0.87899 0.292997 7.2074 0.37524 0.0625 .
Residuals 36 1.46349 0.040652 0.62476
Total 39 2.34248 1.00000
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
55
56
Section
4:
Visualization
4.1 Principal
Components
Analysis
(plotTangentSpace)
Function
plots
a
set
of
Procrustes-‐aligned
specimens
in
tangent
space
along
their
principal
axes,
i.e.,
function
performs
a
Principal
Component
Analysis
(PCA).
Function:
plotTangentSpace(A, axis1 = 1, axis2 = 2, warpgrids = TRUE, mesh = NULL,
label = FALSE, groups = NULL, verbose = FALSE)
Arguments:
A
A
3D
array
(p
x
k
x
n)
containing
landmark
coordinates
for
a
set
of
aligned
specimens
warpgrids
A
logical
value
indicating
whether
deformation
grids
for
shapes
along
X-‐axis
should
be
displayed
mesh
A
mesh3d
object
to
be
warped
to
represent
shape
deformation
along
X-‐axis
(when
warpgrids=TRUE)
as
described
in
warpRefMesh().
axis1
A
value
indicating
which
PC
axis
should
be
displayed
as
the
X-‐axis
(default
=
PC1)
axis2
A
value
indicating
which
PC
axis
should
be
displayed
as
the
X-‐axis
(default
=
PC2)
label
An
optional
vector
indicating
labels
for
each
specimen
are
to
be
displayed
(or
if
TRUE,
numerical
addresses
are
given)
groups
An
optional
factor
vector
specifying
group
identity
for
each
specimen
verbose
A
logical
value
indicating
whether
the
output
is
basic
or
verbose
The
function
performs
a
principal
components
analysis
of
shape
variation
and
plots
two
dimensions
of
tangent
space
for
a
set
of
Procrustes-‐aligned
specimens
(default
is
PC1
vs.
PC2).
The
percent
variation
along
each
PC-‐axis
is
returned.
Additionally
(and
optionally,
warpgrids=T),
deformation
grids
can
be
requested,
which
display
the
shape
of
specimens
at
the
ends
of
the
range
of
variability
along
PC1.
If
groups
are
provided,
specimens
from
each
group
are
plotted
using
distinct
colors
based
on
the
order
in
which
the
groups
are
found
in
the
dataset,
and
using
R's
standard
color
palette:
black,
red,
green,
blue,
cyan,
magenta,
yellow,
and
gray.
The
PCA
can
be
used
to
inspect
the
overall
patterns
of
variation
in
the
sample.
Use
plotOutliers()
(4.2)
if
some
points
seem
very
far
out
of
place.
> data(plethodon)
> Y.gpa<-gpagen(plethodon$land) #GPA-alignment
> gp <- as.factor(paste(plethodon$species, plethodon$site))
> PCA <- plotTangentSpace(Y.gpa$coords, groups = gp)
> PCA
Importance of components:
PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8
Standard deviation 0.04307 0.03958 0.02035 0.01509 0.01314 0.01293 0.01245 0.01119
Proportion of Variance 0.36743 0.31023 0.08201 0.04512 0.03418 0.03312 0.03068 0.02478
Cumulative Proportion 0.36743 0.67767 0.75967 0.80479 0.83897 0.87209 0.90277 0.92755
PC9 PC10 PC11 PC12 PC13 PC14 PC15
Standard deviation 0.009202 0.008289 0.007369 0.006651 0.005116 0.004389 0.004173
Proportion of Variance 0.016770 0.013600 0.010750 0.008760 0.005180 0.003810 0.003450
Cumulative Proportion 0.944320 0.957920 0.968670 0.977430 0.982620 0.986430 0.989880
...
57
> attributes(PCA)
$names
[1] "sdev" "rotation" "center" "scale" "x" "importance"
$class
[1] "summary.prcomp"
$sdev the
standard
deviations
of
the
principal
components
(i.e.,
the
square
roots
of
the
eigenvalues
of
the
covariance/correlation
matrix,
though
the
calculation
is
actually
done
with
the
singular
values
of
the
data
matrix).
$rotation the
matrix
of
variable
loadings
(i.e.,
a
matrix
whose
columns
contain
the
eigenvectors).
$x the
value
of
the
rotated
data
(the
centered
data
multiplied
by
the
rotation
matrix).
Hence,
cov(x)
is
the
diagonal
matrix
diag(sdev^2).
$center the
centering
and
scaling
used.
Note
that
scaling
is
NOT
done.
$scale
58
When
v erbose=TRUE ,
the
function
also
returns
a
list
containing:
the
PC
scores
($pc.scores),
which
can
be
used
by
plot();
and
the
minimum
and
maximum
shapes
($pc.shapes)
on
the
two
PCs
plotted,
which
can
be
used
in
plotRefToTarget().
$pc.scores
PC1 PC2 PC3 PC4 PC5 PC6
[1,] -0.0369931316 0.051182469 -0.0016971188 -3.128812e-03 -0.0109363280 -0.0264503045
[2,] -0.0007493756 0.059420824 0.0001371746 -2.768676e-03 -0.0081174155 0.0139162571
...
$pc.shapes
$pc.shapes$PC1min
[,1] [,2]
[1,] 0.16960517 -0.02807690
[2,] 0.21810341 -0.10340535
...
$pc.shapes$PC1max
[,1] [,2]
[1,] 0.14235007 -0.020486784
[2,] 0.18012044 -0.086122720
...
$pc.shapes$PC2min
[,1] [,2]
[1,] 0.13128088 -0.03616776
[2,] 0.18767216 -0.10979356
...
$pc.shapes$PC2max
[,1] [,2]
[1,] 0.18546661 -0.003640617
[2,] 0.20487416 -0.066270202
...
ProTip!
To
change
colors
of
groups
in
plotTangentSpace
> col.gp<-c(rep("black",10),rep("red",10),rep("yellow",10),rep("orange",10)) # must
not be a factor
> plotTangentSpace(Y.gpa$coords, groups = col.gp)
59
> plotTangentSpace(Y.gpa$coords, groups = col.gp)
mshape
Function:
mshape(A)
Arguments:
A
An
array
(p
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
a
set
of
specimens
The
function
estimates
the
average
landmark
coordinates
for
a
set
of
aligned
specimens.
This
function
is
described
in
Claude
(2008).
> mshape(Y.gpa$coords)
[,1] [,2]
[1,] 0.15263286 -0.023350382
[2,] 0.19445064 -0.092643105
[3,] -0.03361223 -0.007346224
[4,] -0.28069721 -0.092850148
[5,] -0.30998751 -0.061672266
[6,] -0.32557841 -0.036112257
[7,] -0.31804390 0.036125317
[8,] -0.18947114 0.098010904
[9,] 0.02036830 0.099112884
[10,] 0.18852641 0.077278070
[11,] 0.35134313 0.065866300
[12,] 0.55006906 -0.062419094
60
4.2 Find
potential
outliers
(plotOutliers)
Function
plots
a
set
of
Procrustes-‐aligned
specimens
ordered
by
their
distance
from
the
mean
shape.
It
is
used
as
a
tool
to
aid
identifying
specimens
that
have
been
digitized
wrong
(for
example,
mixing
up
landmark
order).
Specimens
falling
outside
of
the
upper
quartile
range
are
potential
outliers.
We
do
not,
however,
stipulate
that
they
must
be
removed
or
are
wrong.
Function:
plotOutliers(A, groups = NULL)
Arguments:
A
A
3D
array
(p
x
k
x
n)
containing
landmark
coordinates
for
a
set
of
aligned
specimens
groups
An
optional
factor
defining
groups
The
function
creates
a
plot
of
all
specimens
ordered
by
their
Procrustes
distance
from
the
mean
shape.
In
the
graph,
the
median
(unbroken
line)
and
upper
and
lower
quartiles
(dashed
lines)
summarize
the
distances
from
the
mean
shape.
Specimens
falling
above
the
upper
quartile
are
plotted
in
red
and
their
address
returned,
for
inspection
by
plotRefToTarget().
> data(plethodon)
# let's make some outliers
> newland <- plethodon$land
> newland[c(1,8),,2] <- newland[c(8,1),,2]
> newland[c(3,11),,26] <- newland[c(11,3),,2]
> Y<- gpagen(newland) # GPA
> plotOutliers(Y$coords)
61
# If there are outliers, then we can view them:
outliers <- plotOutliers(Y$coords) # function returns dimname and address of
outliers
plotRefToTarget(mshape(Y$coords),Y$coords[,,outliers[1]],method="vector", label = T)
plotRefToTarget(mshape(Y$coords),Y$coords[,,outliers[2]],method="vector", label = T)
The
way
that
the
arrows
cross
over
each
other
in
these
two
plots
are
classic
examples
of
when
two
landmarks
have
been
digitized
in
the
wrong
order
(switched).
In
this
case,
either
go
back
to
the
original
specimen
and
redigitize.
Or
in
R,
you
can
switch
the
landmarks:
> mydata[c(8,1),,2] <- mydata[c(1,8),,2] # In this case, landmarks 8 and 1 are
swapped in specimen 2
4.3 Plot
allometric
patterns
in
landmark
data
(plotAllometry)
Function
performs
a
regression
and
plots
allometry
curves
for
a
set
of
specimens.
Function:
plotAllometry(f1, f2 = NULL, groups = NULL, method = c("CAC", "RegScore",
"PredLine"), warpgrids = TRUE, iter = 249, label = NULL, mesh = NULL,
logsz = TRUE, RRPP = FALSE, verbose = FALSE)
Arguments:
f1
A
formula
(of
the
form
shape
~
size);
shape
can
be
a
2D
matrix
(n
x
[p1
x
k])
or
3D
array
(p1
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
the
specimens
f2
An
optional
right
hand
formula
for
groups
(e.g.,
~ groups);
must
be
a
single
factor
method
Method
for
estimating
allometric
shape
components;
see
below
for
details
warpgrids
A
logical
value
indicating
whether
deformation
grids
for
small
and
large
shapes
should
be
displayed
iter
Number
of
iterations
for
significance
testing
label
A
logical
value
indicating
whether
labels
for
each
specimen
should
be
displayed
mesh
A
mesh3d
object
to
be
warped
to
represent
shape
deformation
of
the
directional
and
fluctuating
components
of
asymmetry
if
warpgrids= TRUE
(as
described
in warpRefMesh()).
logsz
A
logical
value
indicating
whether
log(size)
is
used
RRPP
A
logical
value
to
indicate
if
a
randomized
residual
permutation
procedure
(RRPP)
should
be
used
for
statistical
tests
verbose
A
logical
value
indicating
whether
the
output
is
basic
or
verbose
The
function
performs
a
regression
of
shape
on
size,
and
generates
a
plot
that
describes
the
multivariate
relationship
between
size
and
shape
derived
from
landmark
data
(i.e.,
allometry).
The
62
abscissa
of
the
plot
is
log(centroid
size)
while
the
ordinate
represents
shape.
Three
complementary
approaches
can
be
implemented
to
visualize
allometry,
"method=CAC",
"method=RegScore",
"method=PredLine".
For
all
methods,
both
centroid
size
and
allometry
scores
are
returned.
Optionally,
deformation
grids
can
be
requested,
which
display
the
shape
of
the
smallest
and
largest
specimens
relative
to
the
average
specimen
(using
'warpgrids=T'
or
'warpgrids=F').
Finally,
if
groups
are
provided,
the
above
approaches
are
implemented
while
accounting
for
within-‐group
patterns
of
covariation
(see
references
for
explanation).
In
this
case,
the
regression
is
of
the
form:
shape~size+groups
(Note:
to
examine
the
interaction
term
use
procD.lm()).
Specimens
from
each
group
are
plotted
using
distinct
colors
based
on
the
order
in
which
the
groups
are
found
in
the
dataset,
and
using
R's
standard
color
palette:
black,
red,
green,
blue,
cyan,
magenta,
yellow,
and
gray.
If
"method=CAC"
(the
default)
the
function
calculates
the
common
allometric
component
of
the
shape
data,
which
is
an
estimate
of
the
average
allometric
trend
within
groups
(Mitteroecker
et
al.
2004).
The
function
also
calculates
the
residual
shape
component
(RSC)
for
the
data.
> data(ratland)
> Y.gpa<-gpagen(ratland) #GPA-alignment
> plotAllometry(Y.gpa$coords ~ Y.gpa$Csize, method="CAC", iter=999)
[1] Natural log of size is used.
df SS MS Rsq F Z P.value
log(Size) 1 0.62808 0.62808 0.74559 474.78 29.244 0.001
Residuals 162 0.21431 0.00132
Total 163 0.84239
63
If
"method=RegScore"
the
function
calculates
shape
scores
from
the
regression
of
shape
on
size,
and
plots
these
versus
size
(Drake
and
Klingenberg
2008).
For
a
single
group,
these
shape
scores
are
mathematically
identical
to
the
CAC
(Adams
et
al.
2013).
> plotAllometry(Y.gpa$coords ~ Y.gpa$Csize, method="RegScore", iter=999)
[1] Natural log of size is used.
df SS MS Rsq F Z P.value
log(Size) 1 0.62808 0.62808 0.74559 474.78 29.381 0.001
Residuals 162 0.21431 0.00132
Total 163 0.84239
If
"method=PredLine"
the
function
calculates
predicted
values
from
a
regression
of
shape
on
size,
and
plots
the
first
principal
component
of
the
predicted
values
versus
size
as
a
stylized
graphic
of
the
allometric
trend
(Adams
and
Nistri
2010)
64
> plotAllometry(Y.gpa$coords ~ Y.gpa$Csize, method="PredLine", iter=999)
[1] Natural log of size is used.
df SS MS Rsq F Z P.value
log(Size) 1 0.62808 0.62808 0.74559 474.78 2.8445 0.1
Residuals 162 0.21431 0.00132
Total 163 0.84239
When
verbose=TRUE,
the
function
returns
a
list
containing
the
ANOVA
table
($ProcDist.lm)
a
matrix
of
allometry
shape
scores
($allom.score),
a
matrix
of
log
centroid
size
($LogCsize),
a
matrix
of
the
predicted
shapes
for
the
regression
($pred.shape)
–
the
latter
of
which
can
be
used
with
plotRefToTarget().
If
"method=CAC"
the
list
also
has
the
residual
shape
component
(RSC)
($resid.shape).
Protip!
This
function
is
designed
to
show
shape
variation
with
log(centroid
size)
for
allometric
study
questions.
It
is
however
possible
to
use
this
function
to
view
shape
changes
associated
with
any
other
continuous
variable
(e.g.,
body
length,
or
precipitation).
The
function
automatically
takes
the
natural
log
of
the
x-‐variable.
Therefore
when
using
this
function
for
variables
that
should
not
be
logged,
simply
input
them
as
the
exponent
(exp(x))
and
ignore
the
x-‐axis
graph
labels.
The
allometric
shape
scores
are
returned
when
verbose=T,
and
these
can
be
used
to
plot
the
graph
how
the
user
wishes.
4.4 Plot
phylogenetic
tree
and
specimens
in
tangent
space
(plotGMPhyloMorphoSpace)
Function
plots
a
phylogenetic
tree
and
a
set
of
Procrustes-‐aligned
specimens
in
tangent
space,
i.e.,
a
phylomorphospace.
This
function
is
also
called
within
physignal().
65
Function:
plotGMPhyloMorphoSpace(phy, A, labels = TRUE, ancStates = TRUE, plot.param = list())
Arguments:
phy
A
phylogenetic
tree
of
class
phylo
-‐
see
read.tree
in
library
ape
A
A
matrix
(n
x
[p
x
k])
or
3D
array
(p
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
a
set
of
specimens
labels
A
logical
value
indicating
whether
taxa
labels
should
be
included
ancStates
A
logical
value
indicating
whether
ancestral
state
values
should
be
returned
plot.param
A
list
of
plotting
parameters
for
the
tips
(t.bg, t.pch, t.cex),
nodes
(n.bg, n.pch, n.cex),
branches
(l.col, lwd),
and
taxa
labels
(txt.cex, txt.adj, txt.col)
The
function
creates
a
plot
of
the
first
two
dimensions
of
tangent
space
for
a
set
of
Procrustes-‐aligned
specimens.
The
phylogenetic
tree
for
these
specimens
is
superimposed
in
this
plot
revealing
how
shape
evolves
(e.g.,
Rohlf
2002;
Klingenberg
and
Gidaszewski
2010).
The
plot
also
displays
the
ancestral
states
for
each
node
of
the
phylogenetic
tree
(obtained
from
fastAnc (package
Phytools;
Revell
2012)),
whose
values
can
optionally
be
returned
(ancStates = TRUE).
> data(plethspecies)
> Y.gpa<-gpagen(plethspecies$land) #GPA-alignment
> plotGMPhyloMorphoSpace(plethspecies$phy,Y.gpa$coords,
plot.param=list(t.bg="blue",txt.col="red",n.cex=1))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
1 0.2125792 -0.01922821 0.2471906 -0.07892868 -0.02517251 -0.01496629 -0.2629617 -0.09523596 -0.2894638
2 0.2136932 -0.02050579 0.2487112 -0.07944352 -0.02570855 -0.01548581 -0.2626363 -0.09476327 -0.2900425
3 0.2148161 -0.01977237 0.2518101 -0.07639755 -0.02210384 -0.01558998 -0.2646108 -0.09551513 -0.2893961
...
4.5 Create
a
mesh3d
object
warped
to
the
mean
shape
(warpRefMesh)
66
A
function
to
take
a
ply
file
and
use
thin-‐plate
spline
method
to
warp
the
file
into
the
estimated
mean
shape
for
a
set
of
aligned
specimens.
This
mesh
is
used
in
functions
where
m esh=
option
is
available.
Function:
warpRefMesh(file, mesh.coord, ref, color = NULL, centered = FALSE)
Arguments:
file
An
ASCII
ply
file
mesh.coord
A
p
x
k
matrix
of
3D
coordinates
digitized
on
the
ply
file.
ref
A
p
x
k
matrix
of
3D
coordinates
made
by
mshape()
color
Color
to
set
the
ply
file
$material.
If
the
ply
already
has
color,
use
NULL.
For
ply
files
without
color,
color=NULL
will
be
plotted
as
grey.
centered
Logical
If
the
data
in
mesh.coords
were
collected
from
a
centered
mesh
(see
below).
Function
takes
a
ply
file
and
its
landmark
coordinates
uses
the
thin-‐plate
spline
method
(Bookstein
1989)
to
warp
the
mesh
into
the
shape
defined
by
a
second
set
of
landmark
coordinates,
usually
those
of
the
mean
shape
for
a
set
of
aligned
specimens.
It
is
highly
recommended
that
the
mean
shape
is
used
as
the
reference
for
warping
(see
Rohlf
1998).
The
workflow
is
as
follows:
1. Calculate
the
mean
shape
using
mshape()
2. Choose
an
actual
specimen
to
use
for
the
warping.
The
specimen
used
as
the
template
for
this
warping
is
recommended
as
one
most
similar
in
shape
to
the
average
of
the
sample,
but
can
be
any
reasonable
specimen
–
do
this
by
eye,
or
use
findMeanSpec()
3. Warp
this
specimen
into
the
mean
shape
using
warpRefMesh()
4. Use
this
average
mesh
where
it
asks
for
a
mesh=
in
the
analysis
functions
and
visualization
functions
For
landmark
coordinates
digitized
with
geomorph
digitizing
functions
centered=TRUE
by
default.
This
refers
to
the
specimen
being
centered
prior
to
landmark
acquisition
in
the
RGL
window.
For
landmark
data
collected
outside
of
geomorph,
centered=FALSE
will
usually
be
the
case.
The
returned
mesh3d
object
is
for
use
in
geomorph
functions
where
shape
deformations
are
plotted
and
mesh=
option
is
available
(plotTangentSpace(), plotAllometry(), bilat.symmetry(), and plotRefToTarget()).
For
example,
> #1
> average <- mshape(Y.gpa$coords) # calculate the mean shape
> #2
> findMeanSpec(Y.gpa$coords) # Identify specimen closest to mean shape (input is a
3D array of GPA-aligned coordinates)
specimen7 # returns the name of the specimen
25 # returns the specimen number (where it appears in the 3D array)
> # 3
> specimen7 <- readmulti.nts("specimen7.nts") # read in original coordinate data
> averagemesh <- warpRefMesh("specimen7.ply", specimen7, average, color=NULL)
The
function
returns
a
mesh3d
object
of
the
mesh
warped
to
the
shape
of
the
average.
It
also
plots
the
imported
mesh
(here
“specimen7”)
and
the
new
warped
mesh:
67
The
function
returns
a
mesh3d
object
of
the
mesh
warped
to
the
shape
of
the
average.
It
also
plots
the
imported
mesh
(here
“specimen7”)
and
the
new
warped
mesh:
Now
the
object
“averagemesh”
from
our
example
above
can
be
used
in
geomorph
functions
where
shape
deformations
are
plotted
(plotTangentSpace(), plotAllometry(), bilat.symmetry(), and
plotRefToTarget()).
The “averagemesh” can also be saved to the working directory using the rgl function writePLY().
findMeanSpec
Function:
findMeanSpec(A)
A
function
to
identify
which
specimen
lies
closest
to
the
estimated
mean
shape
for
a
set
of
aligned
specimens.
A
is
a
3D
array
(p
x
k
x
n)
containing
landmark
coordinates
for
a
set
of
aligned
specimens.
This
function
is
used
to
facilitate
finding
a
specimen
to
use
with
warpRefMesh().
> findMeanSpec(Y.gpa$coords)
specimen7 # returns the name of the specimen
25 # returns the specimen number (where it appears in the 3D array)
4.6 Create
an
outline
object
warped
to
the
mean
shape
(warpRefOutline)
A
function
to
take
an
outline
(defined
by
many
points)
and
use
thin-‐plate
spline
method
to
warp
the
outline
into
the
estimated
mean
shape
for
a
set
of
aligned
specimens.
This
outline
is
used
plotRefToTarget()
where
o utline=
option
is
available.
Function:
warpRefOutline(file, mesh.coord, ref, color = NULL, centered = FALSE)
Arguments:
68
file
A
.txt
or
.csv
file
of
the
outline
point
coordinates,
or
a
.TPS
file
with
OUTLINES=
or
CURVES=
elements
coord
A
p
x
k
matrix
of
2D
coordinates
digitized
on
the
ply
file.
ref
A
p
x
k
matrix
of
2D
coordinates
made
by
mshape()
Function
takes
an
outline
(defined
by
many
points)
with
a
set
of
fixed
landmark
coordinates
and
uses
the
thin-‐plate
spline
method
(Bookstein
1989)
to
warp
the
outline
into
the
shape
defined
by
a
second
set
of
landmark
coordinates,
usually
those
of
the
mean
shape
for
a
set
of
aligned
specimens.
It
is
highly
recommended
that
the
mean
shape
is
used
as
the
reference
for
warping
(see
Rohlf
1998).
For
file,
it
is
necessary
to
have
in
the
working
directory
a
.txt,
.csv,
.TPS
file
containing
coordinate
data
of
the
outline(s).
An
outline
is
made
up
of
many
points,
each
defined
by
an
x
and
y
coordinate.
To
make
an
outline
txt
file
in
ImageJ
(http://imagej.nih.gov/ij/):
1. Import
an
8-‐bit
black
and
white
drawing
of
an
outline
drawn
from
one
of
your
digitized
specimens
a. use
Image
>
Type
>
8-‐bit
to
convert
if
necessary
b. use
Image
>
Adjust
>
Threshold
to
make
B&W
2. Process
>
Binary
>
Skeletonize
the
image
to
find
a
single
(pixel
width
line
around
the
image)
3. Analyze
>
Tools
>
Save
XY
Coordinates
to
save
the
coordinates
of
all
of
the
pixels
(you
may
need
to
invert
the
y
coordinate
option).
This
text
file
will
have
three
columns
–
the
third
is
a
column
of
RGB
values,
and
needs
to
be
deleted.
NOTE:
It
is
important
that
the
coordinate
system
of
these
outline
points
matches
that
of
the
digitized
landmarks.
If
this
is
not
the
case,
digitize
a
fake
specimen
on
this
outline,
and
save
those
landmark
coordinates
to
be
used
in
the
coord argument.
To
make
an
outline
TPS
file
in
tpsDIG2
(http://life.bio.sunysb.edu/morph/soft-‐dataacq.html):
1. Import
an
image
file
using
File
>
Input
source
2. Using
Modes
>
Outline
mode,
highlight
one
outline
on
the
image
3. Right
click
on
the
outline,
and
choose
Save
as
XY
cords,
and
you
will
be
prompted
to
the
number
of
points
you
want
the
outline
to
be
saved
as
(stay
with
the
default
all).
Click
OK
4. Repeat
for
all
outline
segments
5. To
finish,
File
>
Save
data
as...
and
save
a
.tps
file.
Once
you
have
an
outline,
the
workflow
in
R
is
as
follows:
1. Calculate
the
mean
shape
using
mshape()
2. Choose
an
actual
specimen
to
use
for
the
warping.
The
specimen
used
as
the
template
for
this
warping
is
recommended
as
one
most
similar
in
shape
to
the
average
of
the
sample,
but
can
be
any
reasonable
specimen
–
do
this
by
eye,
or
use
findMeanSpec()
3. Warp
this
specimen
into
the
mean
shape
using
warpRefOutline()
4. Use
this
average
outline
where
it
asks
for
a
outline=
in
plotRefToTarget()
For
example,
> #1
> average <- mshape(Y.gpa$coords) # calculate the mean shape
69
> #2
> findMeanSpec(Y.gpa$coords) # Identify specimen closest to mean shape (input is a
3D array of GPA-aligned coordinates)
specimen7 # returns the name of the specimen
25 # returns the specimen number (where it appears in the 3D array)
> # 3
> specimen7 <- readmulti.nts("specimen7.nts") # read in original coordinate data
> av.outline <- warpRefOutline("specimen7outline.txt", specimen7, average)
The
function
returns
a
list
containing
the
outline
($outline)
warped
to
the
shape
of
the
average,
and
.
It
also
plots
the
imported
outline
(here
“specimen7”)
and
the
new
warped
outline:
> attributes(av.outline)
$names
[1] "outline" "npoints"
For
further
visualiations,
use
av.outline$outline
where
outline=
is
specified.
npoints
is
a
list
of
the
number
of
points
for
each
curve,
and
is
currently
not
used
in
geomorph
but
will
be
in
future
versions.
4.7 Plot
landmark
coordinates
for
all
specimens
(plotAllSpecimens)
Function
plots
landmark
coordinates
for
a
set
of
specimens.
Function:
plotAllSpecimens(A, mean = TRUE, links = NULL, pointscale = 1, meansize = 2)
Arguments:
A
A
3D
array
(p
x
k
x
n)
containing
GPA-‐aligned
coordinates
for
a
set
of
specimens
mean
A
logical
value
indicating
whether
the
mean
shape
should
be
included
in
the
plot
links
An
optional
matrix
defining
for
links
between
landmarks
pointscale
An
optional
value
defining
the
size
of
the
points
for
all
specimens
meansize
An
optional
value
defining
the
size
of
the
points
representing
the
average
specimen
The
function
creates
a
plot
of
the
landmark
coordinates
for
all
specimens.
This
is
useful
for
examining
patterns
of
shape
variation
after
GPA.
If
"mean=TRUE",
the
mean
shape
will
be
calculated
and
added
to
the
plot.
Additionally,
if
a
matrix
of
links
is
provided,
the
landmarks
of
the
mean
shape
will
be
connected
by
lines.
The
link
matrix
is
an
m
x
2
matrix,
where
m
is
the
desired
number
of
links.
Each
70
row
of
the
link
matrix
designates
the
two
landmarks
to
be
connected
by
that
link.
The
function
will
plot
either
two-‐
or
three-‐dimensional
data.
Example
for
2D
data
> data(plethodon)
> Y.gpa<-gpagen(plethodon$land)
> plethodon$links
[,1] [,2]
[1,] 4 5
[2,] 3 5
[3,] 2 4
[4,] 1 2
[5,] 1 3
[6,] 6 7
[7,] 7 8
[8,] 8 9
[9,] 9 10
[10,] 10 11
[11,] 11 12
[12,] 12 1
[13,] 1 9
[14,] 1 10
> plotAllSpecimens(Y.gpa$coords,links=plethodon$links)
Example
for
3D
data
> data(scallops)
> gpagen(A=scallops$coorddata, curves=scallops$curvslide,
surfaces=scallops$surfslide)
Protip!
Typing
the
name
of
the
function
in
the
console
brings
up
the
function
code.
The
user
can
look
at
this
code
for
ideas
of
how
to
customize
their
own
graphs.
71
4.8 Plot
shape
differences
between
a
reference
and
target
specimen
(plotRefToTarget)
Function
plots
shape
differences
between
a
reference
and
target
specimen.
Function:
plotRefToTarget(M1, M2, mesh = NULL, method = c("TPS", "vector", "points",
"surface"), mag = 1, links = NULL, label = FALSE, gridPars = NULL, useRefPts =
FALSE,...)
Arguments:
M1
Matrix
of
landmark
coordinates
for
the
first
(reference)
specimen
M2
Matrix
of
landmark
coordinates
for
the
second
(target)
specimen
mesh
A
mesh3d
object
for
use
with
method="surface"
method
Method
used
to
visualize
shape
difference;
see
below
for
details
mag
The
desired
magnification
to
be
used
when
visualizing
the
shape
difference
(e.g.,
mag=2)
links
An
optional
matrix
defining
for
links
between
landmarks
label
A
logical
value
indicating
whether
landmark
numbers
will
be
plotted
gridPars
An
optional
object
made
by
gridPar()
useRefPts
An
option
(logical
value)
to
use
reference
configuration
points
rather
than
target
configuration
points
(when
method
=
"TPS")
–
NOT
RECOMMENDED
FOR
NOVICE
USERS
...
Additional
parameters
(not
covered
by
gridPar)
to
be
passed
to
plot,
plot3d
or
shade3d.
The
function
generates
a
plot
of
the
shape
differences
of
a
target
specimen
relative
to
a
reference
specimen.
The
option
mag
allows
the
user
to
indicates
the
degree
of
magnification
to
be
used
when
displaying
the
shape
difference.
The
function
will
plot
either
two-‐
or
three-‐dimensional
data.
This
function
combines
numerous
plotting
functions
found
in
Claude
(2008).
Four
methods
for
plots
are
available,
TPS, vector, points, surface.
The
function
can
be
used
to
show
shape
deformation
using
shape
coordinates
from
most
analyses.
Below
are
examples
to
visualize
shape
deformations
from
the
mean
shape
to
another
specimen
in
the
dataset.
A
2D
data
example
> data(plethodon)
> Y.gpa<-gpagen(plethodon$land) #GPA-alignment
> ref<-mshape(Y.gpa$coords)
TPS
a
thin-‐plate
spline
deformation
grid
is
generated.
For
3D
data,
this
method
will
generate
thin-‐plate
spline
deformations
in
the
x-‐y
and
x-‐z
planes.
> plotRefToTarget(ref,Y.gpa$coords[,,39],
method="TPS")
> plotRefToTarget(ref,Y.gpa$coords[,,39],mag=3,
method="TPS") #magnify difference by 3X
72
vector
a
plot
showing
the
vector
displacements
between
corresponding
landmarks
in
the
reference
and
target
specimen
is
shown.
>
plotRefToTarget(ref,Y.gpa$coords[,,39],me
thod="vector", mag=3)
points
a
plot
is
displayed
with
the
landmarks
in
the
target
(black)
overlaying
those
of
the
reference
(gray).
Additionally,
if
a
matrix
of
links
is
provided,
the
landmarks
of
the
mean
shape
will
be
connected
by
lines.
The
link
matrix
is
an
M
x
2
matrix,
where
M
is
the
desired
number
of
links.
Each
row
of
the
link
matrix
designates
the
two
landmarks
to
be
connected
by
that
link.
> plotRefToTarget(ref,Y.gpa$coords[,,39],method="points", mag=3)
73
Using
links
(wireframe)
for
representation
of
your
specimen.
In
T PS
,
v ector
&
p oints
in
both
2D
and
3D
it
is
possible
to
add
links
to
these
plots.
The
links
argument
can
be
made
by
hand,
using
matrix(),
or
there
is
a
graphical
assisted
function
define.links()
detailed
below.
In
the
plethodon
list,
there
is
a
matrix
called
plethodon$links
[,1] [,2]
[1,] 4 5
[2,] 3 5
[3,] 2 4
[4,] 1 2
[5,] 1 3
[6,] 6 7
[7,] 7 8
[8,] 8 9
[9,] 9 10
[10,] 10 11
[11,] 11 12
[12,] 12 1
[13,] 1 9
[14,] 1 10
>
plotRefToTarget(ref,Y.gpa$coords[,,39],method
="points",
mag=3,
links
=
plethodon$links)
Warping
a
2D
outline
of
your
specimen.
In
both
T PS
&
p oints
it
is
possible
to
add
an
outline
to
these
plots.
For
more
information
on
creating
and
importing
an
outline,
see
warpRefOutline().
> plotRefToTarget(ref,Y.gpa$coords[,,39], method = “TPS”, outline=plethodon$outline)
74
> plotRefToTarget(ref,Y.gpa$coords[,,39], mag=2, method = “points”,
outline=plethodon$outline)
A
3D
data
example
using
the
three
methods
shown
above
> data(scallops)
> Y.gpa<-gpagen(A=scallops$coorddata, curves=scallops$curvslide,
surfaces=scallops$surfslide)
> ref<-mshape(Y.gpa$coords)
> plotRefToTarget(ref,Y.gpa$coords[,,1],method="TPS", mag=3)
75
surface
a
mesh3d
surface
is
warped
using
thin-‐plate
spline
(for
3D
data
only).
Requires
mesh3d
object
in
option
mesh=,
preferably
made
using
warpRefMesh() 4.5,
which
provides
a
mesh3d
object
that
is
the
shape
of
the
sample
mean.
It
is
recommended
that
the
mean
shape
is
used
as
the
reference
for
warping
(see
Rohlf
1998).
A
3D
data
example
using
the
average
mesh
made
with
warpRefMesh()
(Note:
this
example
is
not
included
in
the
geomorph
package,
but
show
here
for
illustrative
purposes).
> # averagemesh is a mesh made with warpRefMesh, that is the shape of the mean of a
set of specimens
> ref <- mshape(Y.gpa$coords) # calculate the mean shape from a set of GPA-aligned
specimens
> plotRefToTarget(M1=ref, M2=Y.gpa$coords[,,1], mesh=averagemesh, method="surface")
Function
plots
the
warped
“target”
shape
(shown
here
against
the
mean
for
illustrative
purposes
only).
This
function
can
be
used
to
show
deformations
between
any
two
sets
of
coordinates.
Coordinate
data
are
provided
by
several
functions,
a
few
examples
given
below.
76
Example
1,
for
plotTangentSpace() verbose=TRUE
returns
a
list
containing
shape
coordinates
($pc.shapes)
for
the
minimum
and
maximum
shape
on
the
two
PCs
plotted
(default
is
PC1
and
PC2)
as
four
matrices.
To
use,
enter
the
coordinate
matrix
into
position
M2,
e.g.
> data(plethodon)
> Y.gpa<-gpagen(plethodon$land) #GPA-alignment
> ref <- mshape(Y.gpa$coords)
> res <- plotTangentSpace(Y.gpa$coords, groups = paste(plethodon$species,
plethodon$site), verbose=TRUE)
> plotRefToTarget(M1=ref, M2=res$pc.shapes$PC1min, method="TPS") #shape change along
PC1 in the negative direction
> plotRefToTarget(M1=ref, M2=res$pc.shapes$PC1max, method="TPS") #shape change along
PC1 in the positive direction
Example
2,
for
plotAllometry()
verbose=TRUE returns
a
list
containing
the
predicted
shape
scores
($pred.shape).
To
use,
plot
the
minimum
or
maximum
of
this
array
in
M2,
e.g.,
> data(ratland)
> Y.gpa<-gpagen(ratland) #GPA-alignment
> ref<-mshape(Y.gpa$coords)
> res <- plotAllometry(Y.gpa$coords ~ Y.gpa$Csize,method="RegScore", verbose=TRUE)
> plotRefToTarget(ref, res$pred.shape[,,which.max(Y.gpa$Csize)],method="TPS") #
Predicted shape at max centrod size
> plotRefToTarget(ref, res$pred.shape[,,which.min(Y.gpa$Csize)],method="TPS") #
Predicted shape at min centrod size
Example
3,
for
two.b.pls(), morphol.integr( method=”PLS”) and phylo.pls()
verbose=TRUE
returns
the
PLS
scores
for
block
1
and
block
2
($Xscores, $Yscores).
M2
plots
the
actual
specimen
that
is
at
the
maximum
or
minimum
of
block
1.
For
example,
taking
the
minimum
and
maximum
along
the
Xblock
1
PLS
1,
e.g.,
> res <- morphol.integr(Y.gpa$coords[1:5,,], Y.gpa$coords[6:12,,],
method="PLS",iter=99,verbose=TRUE)
> ref <- mshape(Y.gpa$coords)
> plotRefToTarget(ref,Y.gpa$coords[,,which.min(res$x.scores)],method="TPS") #Min
along PLS1
> plotRefToTarget(ref,Y.gpa$coords[,,which.max(res$x.scores)],method="TPS") #Max
along PLS1
Example
4,
for
viewing
differences
between
groups
(shown
to
be
significantly
different
with
procD.lm()),
first
average
the
data
by
groups,
calculate
group
means
and
plot
those
means.
> data(plethodon)
> Y.gpa<-gpagen(plethodon$land) #GPA-alignment
> y <- two.d.array(Y.gpa$coords)
> means <- aggregate(y ~ plethodon$site, FUN=mean)
> means
plethodon$site V1 V2 V3 V4 V5 V6 V7
V8
1 Allo 0.1397395 -0.02535584 0.1832314 -0.09279558 -0.02462463 -0.006231783 -0.2797076 -
0.09041826
2 Symp 0.1655262 -0.02134492 0.2056699 -0.09249063 -0.04259982 -0.008460664 -0.2816868 -
0.09528204
77
...
> Allo.mn <- matrix(as.numeric(means[1,-1]), ncol=2, byrow=T) #makes as matrix
> ref<-mshape(Y.gpa$coords)
> plotRefToTarget(ref, Allo.mn, method="TPS") # Means shape of group
78
define.links
Function:
define.links(spec, ptsize)
Arguments:
spec
Name
of
specimen,
as
an
object
matrix
containing
2D
or
3D
landmark
coordinates
ptsize
Size
of
the
landmarks
plotted
Function
takes
a
matrix
of
digitized
landmark
coordinates
(e.g.
from
mshape())
and
allows
the
user
to
define
pairs
of
landmarks
to
be
linked,
for
visualization
purposes.
The
output
is
a
matrix
to
be
used
by
plotAllSpecimens()
&
plotRefToTarget()
option
'links='.
Selection
In
the
plot
window
select
two
landmarks
that
will
be
linked.
In
the
console,
the
user
will
be
prompted
to
continue
linking
landmarks
to
build
the
wireframe
or
end
the
session
(typing
y
or
n
respectively).
For
2D
data
in
plot
window,
use
LEFT
mouse
button
to
select
landmarks.
For
3D
data
in
rgl
window,
use
RIGHT
mouse
button
(or
command+LEFT
for
mac)
to
select
landmarks.
Example
with
the
plethodon
dataset
> data(plethodon)
> Y.gpa<-gpagen(plethodon$land) #GPA-
alignment
> links <- define.links(plethodon$land[,,1])
Select landmarks to link
link made between landmarks 1 & 2
Continue? type y/n
79
gridPar
Function:
gridPar(pt.bg = "gray", pt.size = 1.5, link.col = "gray", link.lwd = 2,
link.lty = 1, out.col = "gray", out.cex = 0.1, tar.pt.bg = "black",
tar.pt.size = 1, tar.link.col = "black", tar.link.lwd = 2,
tar.link.lty = 1, tar.out.col = "black", tar.out.cex = 0.1,
n.col.cell = 20, grid.col = "black", grid.lwd = 1, grid.lty = 1,
txt.adj = 0.5, txt.pos = 1, txt.cex = 0.8, txt.col = "black")
Arguments
for
the
reference:
pt.bg
Background
color
of
reference
configuration
points
(single
value
or
vector
of
values)
pt.size
Scale
factor
for
reference
configuration
points
(single
value
or
vector
of
values)
link.col
The
color
of
links
for
reference
configurations
(single
value
or
vector
of
values)
link.lwd
The
line
weight
of
links
for
reference
configurations
(single
value
or
vector
of
values)
link.lty
The
line
type
of
links
for
reference
configurations
(single
value
or
vector
of
values)
out.col
The
color
of
outline
for
reference
configurations
(single
value
or
vector
of
values)
out.cex
The
size
of
plotting
symbol
of
outline
for
reference
configurations
(single
value
or
vector
of
values)
Arguments
for
the
target:
tar.pt.bg
Background
color
of
target
configuration
points
(single
value
or
vector
of
values)
tar.pt.size
Scale
factor
for
target
configuration
points
(single
value
or
vector
of
values)
tar.link.col
The
color
of
links
for
target
configurations
(single
value
or
vector
of
values)
tar.link.lwd
The
line
weight
of
links
for
target
configurations
(single
value
or
vector
of
values)
tar.link.lty
The
line
type
of
links
for
target
configurations
(single
value
o r
vector
of
values)
tar.out.col
The
color
of
outline
for
target
configurations
(single
value
or
vector
of
values)
tar.out.cex
The
size
of
plotting
symbol
of
outline
for
target
configurations
(single
value
or
vector
of
values)
Arguments
for
the
grid
and
text:
n.col.cell
The
number
of
square
cells
(along
x
axis)
for
grids
(single
numerical
value)
grid.col
The
color
of
grid
lines
(single
value)
grid.lwd
Scale
factor
for
the
weight
of
grid
lines
(single
numerical
value)
grid.lty
The
line
type
for
grid
lines
(single
numerical
value,
as
in
base
R
plot)
txt.adj
The
adjustment
value
of
the
landmark
label
(one
or
two
values,
as
in
base
R
text)
txt.pos
The
position
of
the
landmark
label
(single
numerical
value,
as
in
base
R
text)
txt.cex
The
size
of
the
landmark
label
text
(single
numerical
value)
txt.col
The
color
of
the
landmark
label
text
(single
numerical
value)
The
function
allows
users
to
vary
certain
plotting
parameters
to
produce
different
graphical
outcomes
for
plotRefToTarget().
Not
all
parameters
need
to
be
adjusted
to
use
this
function.
e.g.
Altering
points
and
links
> GP <- gridPar(pt.bg = "red", pt.size = 1,
link.col="blue", link.lwd=2, n.col.cell=50)
> plotRefToTarget(ref,Y.gpa$coords[,,39],
gridPars=GP, mag=2, links=plethodon$links,
method="TPS")
80
e.g.
Altering
text
labels
and
point
colour
> GP <- gridPar(pt.bg = "green", pt.size = 1,
txt.pos = 3, txt.col = "red")
> plotRefToTarget(ref,Y.gpa$coords[,,39],
gridPars=GP, mag=3, method="vector",
label=T)
The
function
returns
an
object
that
is
used
by
plotRefToTarget(...,gridPars =).
The
same
arguments
are
used
for
both
2D
and
3D
data.
81
4.9 Plot
3D
specimen,
fixed
landmarks
and
surface
semilandmarks
(plotspec)
A
function
to
plot
three-‐dimensional
(3D)
specimen
along
with
its
landmarks.
Function:
plotspec(spec, digitspec, fixed = NULL, ptsize = 1, centered = FALSE, ...)
Arguments:
spec
An
object
of
class
shape3d/mesh3d,
or
matrix
of
3D
vertex
coordinates.
digitspec
Name
of
data
matrix
containing
3D
fixed
and/or
surface
sliding
coordinates.
fixed
Numeric
The
number
of
fixed
template
landmarks
(listed
first
in
digitspec)
ptsize
Numeric
Size
to
plot
the
mesh
points
(vertices),
e.g.,
0.1
for
dense
meshes,
3
for
sparse
meshes
centered
Logical
Whether
the
data
matrix
is
in
the
surface
mesh
coordinate
system
(centered=FALSE)
or
if
the
data
were
collected
after
the
mesh
was
centered
(centered=TRUE)-‐
see
details.
...
additional
parameters
which
will
be
passed
to
plot3d.
Function
to
plot
3D
specimens
along
with
their
digitized
"fixed"
landmarks
and
semilandmarks
"surface
sliders"
and
"curve
sliders".
If
specimen
is
a
3D
surface
(class
shape3d/mesh3d)
mesh
is
plotted.
For
visualization
purposes,
3D
coordinate
data
collected
using
digit.fixed() or
digitsurface()
and
buildtemplate()
prior
to
build
1.1-‐6
were
centered
by
default.
Therefore
use
this
function
with
centered=TRUE.
Data
collected
outside
geomorph
should
be
read
using
centered=FALSE.
The
function
assumes
the
fixed
landmarks
are
listed
at
the
beginning
of
the
coordinate
matrix
(digitspec).
> data(scallopPLY)
> ply <- scallopPLY$ply
> digitdat <- scallopPLY$coords
> plotspec(spec=ply,digitspec=digitdat,fixed=16, centered =TRUE)
82
Section
5:
Data
Collection
(Digitizing)
5.1 2D
data
collection
(digitize2d)
An
interactive
function
to
digitize
two-‐dimensional
landmarks
from
.jpg
files.
This
function
works
very
similarly
to
TPSdig
software
by
J.
Rohlf,
allowing
a
list
of
files
to
be
processed
sequentially.
Function:
digitize2d(filelist, nlandmarks, scale = NULL, tpsfile, verbose = TRUE)
Arguments:
filelist
A
list
of
names
of
jpeg
images
to
be
digitized.
nlandmarks
Number
of
landmarks
to
be
digitized.
scale
An
optional
vector
containing
the
length
of
the
scale
to
be
placed
on
each
image.
tpsfile
The
name
of
a
TPS
file
to
be
created
or
read.
verbose
User
decides
whether
to
digitize
in
verbose
or
silent
format
(see
details),
default
is
verbose
This
function
may
be
used
for
digitizing
2D
landmarks
from
jpeg
images
(.jpg).
The
user
provides
a
list
of
image
names,
the
number
of
landmarks
to
be
digitized,
and
the
name
of
an
output
TPS
file.
The
list
can
be
made
manually,
using
c() or list.files() base
functions
e.g.,
> filelist <- c("specimen1.jpg", "specimen1.jpg")
> # or
> filelist <- list.files(pattern = "*.jpg").
Digitizing
landmarks
from
2D
photos
requires
that
a
scale
bar
is
placed
in
the
image
in
order
to
scale
the
coordinate
data.
The
'scale'
option
requires:
a
single
number
(e.g.
10)
which
means
that
the
scale
to
be
measured
in
all
images
is
a
10mm
scale
bar;
OR
a
vector
the
same
length
as
the
filelist
containing
a
number
for
the
scale
of
each
image.
If
scale=NULL,
then
the
digitized
coordinates
will
not
be
scaled.
This
option
is
NOT
recommended.
Landmarks
to
be
digitized
can
include
both
fixed
landmarks
and
semi-‐landmarks,
the
latter
of
which
are
to
be
designated
as
"sliders"
for
subsequent
analysis
(see
the
function
define.sliders()).
Users
may
digitize
all
specimens
in
one
session,
or
may
return
at
a
later
time
to
complete
digitizing.
In
the
latter
case,
the
user
provides
the
same
filelist
and
TPS
file
and
the
function
will
determine
where
the
user
left
off.
If
specimens
have
missing
landmarks,
these
can
be
incorporated
during
the
digitizing
process
using
the
'a'
option
as
described
below
(a
=
absent).
Digitizing:
Digitizing
landmarks
involves
landmark
selection
using
a
mouse
in
the
plot
window,
using
the
LEFT
mouse
button
(or
regular
button
for
Mac
users):
Digitize
the
scale
bar
by
selecting
the
two
end
points
(single
click
for
start
and
end).
The
user
is
asked
whether
the
system
should
keep
or
discard
the
digitized
scale
bar.
> digitize2d(filelist nlandmarks=11, scale=3, tpsfile = "salamaders.tps").,verbose =
TRUE)
Only 1 scale measure provided. Will use scale = 3 for all specimens.
Digitizing specimen 1 in filelist
Set scale = 3
83
Keep scale (y/n)?
y
Now,
digitize
each
landmark
with
single
click
and
the
landmark
is
shown
in
red.
Select landmarks 1:11
If
verbose = TRUE,
digitizing
is
interactive
between
landmark
selection
using
a
mouse
and
the
R
console.
Once
a
landmark
is
selected,
the
user
is
asked
if
the
system
should
keep
or
discard
the
selection
(y/n/a).
If
"y",
the
user
is
asked
to
continue
to
select
the
next
landmark.
If
"n",
the
user
is
asked
to
select
it
again.
To
digitize
a
missing
landmark,
simply
click
on
any
location
in
the
image.
Then,
when
prompted
to
keep
selection,
choose
'a'
(for
absent).
Missing
landmarks
can
only
be
included
during
the
digitizing
process
when
verbose=TRUE.
If
verbose = FALSE
(as
in
the
example
above)
the
digitizing
of
landmarks
is
continuous
and
uninterrupted.
Here
the
user
will
not
be
prompted
to
approve
each
landmark
selection.
At the end of digitizing, the landmark coordinates and the scale are written to a TPS file.
84
salamander.tps
LM = 11
0.913794820018337 0.728605670332276
1.04745503254995 0.58684483885935
0.654575013896415 0.765058455568172
0.168537877417812 0.671901337743106
0.103732925887331 0.736706289273586
0.0551292122394711 0.813662169216032
0.103732925887331 0.927070834394373
0.330550256244013 1.04452980904337
0.686977489661655 1.00402671433682
1.03530410413799 0.927070834394373
1.71575609520803 0.643549171448521
ID=mvz206608l
...
5.2 Define
sliding
semilandmarks
(define.sliders)
An
interactive
function
to
define
which
landmarks
will
"slide"
along
curves.
Function:
define.sliders(spec, nsliders, surfsliders = FALSE)
Arguments:
spec
Name
of
specimen,
as
an
object
matrix
containing
2D
or
3D
landmark
coordinates
nsliders
Number
of
landmarks
to
be
semilandmarks
that
slide
along
curves
surfsliders
Logical
(3D
only)
If
'spec'
contains
landmarks
that
are
"surface
sliders",
made
by
buildtemplate(),
"surfslide.csv"
should
be
in
working
directory
Function
takes
a
matrix
of
digitized
landmark
coordinates
and
helps
user
choose
which
landmarks
will
be
treated
as
"curve
sliders"
in
Generalized
Procrustes
analysis
gpagen().
This
type
of
semilandmark
"slides"
along
curves
lacking
known
landmarks
(see
Bookstein
1997
for
algorithm
details).
Each
sliding
semilandmark
("sliders")
will
slide
between
two
designated
points,
along
a
line
tangent
to
the
specified
curvature.
Selection
in
2D:
Choosing
which
landmarks
will
be
sliders
involves
landmark
selection
using
a
mouse
in
the
plot
window.
To
define
the
sliders,
for
each
sliding
landmark
along
the
curve
in
the
format
'before-‐slider-‐after',
using
the
LEFT
mouse
button
(or
regular
button
for
Mac
users),
click
on
the
hollow
circle
to
choose
the
landmark
in
the
following
order:
1)
Click
to
choose
the
first
landmark
between
which
semi-‐landmark
will
"slide",
2)
Click
to
choose
sliding
landmark,
3)
Click
to
choose
the
last
landmark
between
which
semi-‐landmark
will
"slide".
Selected
landmarks
will
be
filled
in
and
lines
are
drawn
connecting
the
three
landmarks,
and
will
highlight
the
sliding
semilandmark
in
red
and
the
flanking
landmarks
in
blue.
> data(hummingbirds)
> define.sliders(hummingbirds$land[,,1], nsliders=10)
85
Selection
in
3D:
To
define
the
sliders,
for
each
sliding
landmark
along
the
curve
in
the
format
'before-‐
slider-‐after',
using
RIGHT
mouse
button
to
select:
1)
Click
on
landmark
to
choose
the
first
landmark
between
which
semi-‐landmark
will
"slide",
2)
Click
box
to
choose
sliding
landmark,
3)
Click
box
to
choose
the
last
landmark
between
which
semi-‐landmark
will
"slide",
Screen
will
show
lines
connecting
the
three
landmarks,
and
will
highlight
the
sliding
semilandmark
in
red.
> define.sliders(16,11)
86
semilandmark 9 slides between landmarks 5 and 10
This
procedure
is
overlapping,
so
for
example
a
curve
defined
by
a
sequence
of
semilandmarks,
the
user
must
select
the
2nd
point
of
the
first
three
to
be
the
1st
for
the
next
e.g.,
1
2
3
then
2
3
4,
etc.
Function
returns
a
'curves
x
3'
matrix
containing
the
landmark
address
of
the
curve
sliders,
indicating
the
points
between
which
the
selected
point
will
"slide",
written
to
the
working
directory
as
"curveslide.csv".
curveslide.csv
before slide after
5 9 10
9 10 7
10 7 11
7 11 12
11 12 6
12 6 13
6 13 14
13 14 8
14 8 15
8 15 16
15 16 1
which
can
be
read
in
for
use
with
gpagen():
> curves <- as.matrix(read.csv("curveslide.csv", header=T))
87
5.3 Importing
3D
surface
files
(read.ply)
A
function
to
read
ply
files,
which
can
be
used
for
digitizing
landmark
coordinates
or
for
shape
warps.
Other
3D
file
formats
are
currently
not
supported.
Other
files
can
be
converted
to
ply
using
for
example
Meshlab
(http://meshlab.sourceforge.net).
Function:
read.ply(file, ShowSpecimen = TRUE, addNormals = TRUE)
Arguments:
file
An
ASCII
ply
file
ShowSpecimen
A
logical
value
indicating
whether
or
not
the
ply
file
should
be
displayed
addNormals
A
logical
value
indicating
whether
or
not
the
normal
of
each
vertex
should
be
calculated
(using
addNormals
[rgl])
Function
reads
three-‐dimensional
surface
data
in
the
form
of
a
single
ply
file
(Polygon
File
Format;
ASCII
format
only,
from
3D
scanners
such
as
NextEngine
and
David
scanners).
Vertices
of
the
surface
may
then
be
used
to
digitize
three-‐dimensional
points,
and
semilandmarks
on
curves
and
surfaces.
The
function
opens
the
ply
file
and
plots
the
mesh,
with
faces
rendered
if
file
contains
faces,
and
colored
if
the
file
contains
vertex
color.
> # usage, reading a file called myply.ply in the working directory
> read.ply(“myply.ply”, ShowSpecimen=TRUE)
$class
[1] "mesh3d" "shape3d"
> plot3d(myply)
88
> # change color of mesh
> myply$material <- "gray" # using color word
> myply$material <- "#FCE6C9" # using RGB code
5.4 3D
data
collection:
landmarks
(digit.fixed)
An
interactive
function
to
digitize
three-‐dimensional
(3D)
landmarks.
Input
for
the
function
is
either
a
matrix
of
vertex
coordinates
defining
a
3D
surface
object
or
a
mesh3d
object
as
obtained
from
read.ply().
Function:
digit.fixed(spec, fixed, index = FALSE, ptsize = 1, center = TRUE)
Arguments:
spec
An
object
of
class
shape3d/mesh3d,
or
matrix
of
3D
vertex
coordinates
fixed
Numeric
The
number
landmarks
(fixed,
and
curve
sliders
if
desired)
index
Logical
Whether
selected
landmark
addresses
should
be
returned
ptsize
Numeric
Size
to
plot
the
mesh
points
(vertices),
e.g.,
0.1
for
dense
meshes,
3
for
sparse
meshes
center
Logical
Whether
the
object
'spec'
should
be
centered
prior
to
digitizing
(default
center=TRUE)
Function
for
digitizing
"n"
three-‐dimensional
landmarks.
The
landmarks
are
"fixed"
(traditional
landmarks).
They
can
be
later
designated
as
"curve
sliders"
(semilandmarks,
that
will
"slide"
along
curves
lacking
known
landmarks
if
required.
A
sliding
semi-‐landmark
("sliders")
will
slide
between
two
designated
points,
along
a
line
tangent
to
the
specified
curvature,
and
must
be
defined
as
"sliders"
using
function
define.sliders()
or
with
similar
format
matrix
made
outside
R.
For
3D
"surface
sliders"
(surface
semilandmarks
that
slide
over
a
surface)
the
function
digitsurface()
should
be
used
instead.
NOTE:
Function
centers
the
mesh
before
digitizing
by
default
(center=TRUE).
If
one
chooses
not
to
center,
specimen
may
be
difficult
to
manipulate
in
rgl
window.
Digitizing:
3D
Digitizing
functions
in
geomorph
are
interactive
between
landmark
selection
using
a
mouse
(see
below
for
instructions),
and
the
R
console.
Once
a
point
is
selected,
the
user
is
asked
if
the
system
should
keep
or
discard
the
selection
(y/n).
If
"y",
the
user
is
asked
to
continue
to
select
the
next
landmark.
If
"n"
the
removes
the
last
chosen
landmark,
and
the
user
is
asked
to
select
it
again.
This
can
be
repeated
until
the
user
is
comfortable
with
the
landmark
chosen.
89
To
digitize
with
a
standard
3-‐button
(PC):
• the
RIGHT
mouse
button
(primary)
to
select
points
to
be
digitized
(click
on
a
vertex
to
select)
• the
LEFT
mouse
button
(secondary)
is
used
to
rotate
mesh,
• the
mouse
SCROLLER
(third/middle)
is
used
to
zoom
in
and
out.
NOTE:
Digitizing
functions
on
MACINTOSH
computers
using
a
standard
3-‐button
mice
works
as
specified.
Macs
using
platform
specific
single
button
mice:
• press
button
to
rotate
3D
mesh,
• press
button
while
pressing
COMMAND
key
to
select
points
to
be
digitized
(click
on
a
vertex
to
select)
• press
button
while
pressing
OPTION
key
to
adjust
mesh
perspective.
• the
mouse
SCROLLER
or
trackpad
two
finger
scroll
is
used
to
zoom
in
an
out.
XQuartz
must
be
configured:
go
to
Preferences
>
Input
>
tick
“Emulate
three
button
mouse”.
NOTE:
there
is
no
pan
(translate)
functionality
in
rgl
library
for
all
platforms
at
this
time.
This
is
why
the
function
has
a
center=TRUE/FALSE
option.
Example,
reading
in
a
mesh
with
24700
vertices,
> mandible <- read.ply("Mandible.ply")
> digit.fixed(mandible, fixed=20, index=F, ptsize=1, center=T)
Select Landmark 1 #
Keep landmark 1(y/n)? #See picture step 2
y
Select Landmark 2 #See picture step 2
Keep landmark 2(y/n)?
y
Select Landmark 3 #See picture step 1
90
Function
writes
to
the
working
directory
an
NTS
file
with
the
name
of
the
specimen
and
.nts
suffix
containing
the
landmark
coordinates.
mandible.nts
"mandible
1 20 3 0 dim=3
13.2628089578878 10.2361171749175 -3.49646546534654
9.32980895788779 18.7309171749175 -1.94616546534654
-2.70691104211221 17.5351171749175 0.852234534653466
-13.7911610421122 15.6363171749175 0.945934534653464
-14.1681010421122 6.40941717491749 0.853034534653467
...
If
index=FALSE
(default)
function
returns
to
the
console
an
n
x
3
matrix
containing
the
x,y,z
coordinates
of
the
digitized
landmarks.
If
index=TRUE,
function
returns
a
list
containing
a
matrix
containing
the
x,y,z
coordinates
of
the
digitized
landmarks
($selected)
and
a
matrix
of
addresses
for
landmarks
that
are
"fixed"
($fix,
primarily
for
internal
use).
YouTube
video
of
this
function
in
action
here:
http://youtu.be/VK6bLbb4ipY
5.5 3D
data
collection:
landmarks
and
semilandmarks
buildtemplate
An
interactive
function
to
build
template
of
three-‐dimensional
surface
sliding
semilandmarks.
Input
for
the
function
is
either
a
matrix
of
vertex
coordinates
defining
a
3D
surface
object
or
a
mesh3d
object
as
obtained
from
read.ply().
buildtemplate(spec, fixed, surface.sliders, ptsize = 1, center = TRUE)
Arguments:
spec
Name
of
surface
file,
as
either
an
object
of
class
shape3d/mesh3d,
or
matrix
of
three-‐dimensional
vertex
coordinates.
fixed
Either:
a
single
value
designating
the
number
of
fixed
template
landmarks
to
be
selected
by
digit.fixed,
OR
a
p-‐x-‐k
matrix
of
3D
coordinates
collected
previously
(e.g.
in
other
software)
surface.sliders
The
number
of
template
surface
sliders
desired
ptsize
Size
to
plot
the
mesh
points
(vertices),
e.g.,
0.1
for
dense
meshes,
3
for
sparse
meshes
center
Logical
Whether
the
object
'spec'
should
be
centered
prior
to
digitizing
(default
center=TRUE)
Function
constructs
a
template
of
fixed
landmarks
and
n
"surface
sliders",
semilandmarks
that
slide
over
a
surface.
The
user
digitizes
the
fixed
points,
then
the
function
finds
n
surface
semilandmarks
following
algorithm
outlined
in
Gunz
et
al.
(2005)
and
Mitteroecker
and
Gunz
(2009).
Surface
semilandmarks
are
roughly
equidistant
set
of
predetermined
number
of
points,
chosen
over
the
mesh
automatically
using
a
nearest-‐neighbor
approach.
The
set
of
fixed
and
surface
slider
landmarks
are
exported
as
a
"template",
which
is
used
to
extract
a
set
of
similarly
numbered
landmarks
on
every
specimen
using
function
digitsurface().
Some
of
the
"fixed"
landmarks
can
be
later
designated
as
"curve
sliders"
using
function
define.sliders()
if
required
-‐
see
details
in
digit.fixed().
To
ensure
a
strong
match
between
the
scan
and
the
template,
it
is
recommended
that
a
reasonable
number
of
fixed
points
be
used.
These
fixed
points
can
be
designated
as
"curve
sliders"
later
using
function
define.sliders(),
see
the
function
digit.fixed()
for
details.
NOTE:
Function
centers
the
mesh
before
digitizing
by
default
(center=TRUE).
If
one
chooses
not
to
center,
specimen
may
be
difficult
to
manipulate
in
rgl
window.
91
Digitizing:
as
before
in
digit.fixed().
Example,
digitizing
16
landmarks
on
a
mesh
and
then
automatically
calculate
150
surface
sliding
semilandmarks
> myply1 <- read.ply("myply1.ply", ShowSpecimen=FALSE)
> buildtemplate(myply1, 16, 150, ptsize=1)
Select Landmark 1 #See picture step 1
Keep landmark 1(y/n)? #See picture step 2
y
Select
all
of
the
fixed
landmarks,
and
then
the
function
will
calculate
the
position
of
the
surface
sliding
landmarks
on
the
mesh,
and
plot
them
in
blue.
92
Function
writes
to
the
working
directory
three
files:
an
NTS
file
with
the
name
of
the
specimen
and
.nts
suffix
containing
the
landmark
coordinates,
"template.txt"
containing
the
same
coordinates
for
use
with
the
function
digitsurface(),
and
"surfslide.csv",
a
file
containing
the
address
of
the
landmarks
defined
as
"surface
sliders"
for
use
with
gpagen().
Function
also
returns
to
console
an
n
x
3
matrix
containing
the
x,y,z
coordinates
of
the
digitized
landmarks.
myply1.nts
"myply1
1 166 3 0 dim=3
13.2628089578878 10.2361171749175 -3.49646546534654
9.32980895788779 18.7309171749175 -1.94616546534654
-2.70691104211221 17.5351171749175 0.852234534653466
-13.7911610421122 15.6363171749175 0.945934534653464
-14.1681010421122 6.40941717491749 0.853034534653467
...
template.txt
"xpts" "ypts" "zpts"
13.2628089578878 10.2361171749175 -3.49646546534654
9.32980895788779 18.7309171749175 -1.94616546534654
-2.70691104211221 17.5351171749175 0.852234534653466
-13.7911610421122 15.6363171749175 0.945934534653464
-14.1681010421122 6.40941717491749 0.853034534653467
...
93
surfslide.csv
x
17
18
19
20
21
22
23
...
editTemplate
An
interactive
function
to
remove
landmarks
from
a
3D
template
file.
Function:
editTemplate(template, fixed, n)
Arguments:
template
Matrix
of
template
3D
coordinates.
fixed
Number
of
"fixed"
landmark
points
(non
surface
sliding
points)
n
Number
of
points
to
be
removed
Function
edits
a
'template.txt'
file
made
by
buildtemplate(),
which
must
be
in
current
working
directory.
Function
overwrites
'template.txt'
in
working
directory
with
edited
version.
Use
read.table("template.txt",
header
=
T).
> template <- as.matrix(read.table("template.txt", header=T, sep=" "))
> editTemplate(template, fixed=16, n=2)
Remove Template Points
1 of 2 points have been removed
2 of 2 points have been removed
94
digitsurface
An
interactive
function
to
digitize
three-‐dimensional
(3D)
landmarks
on
a
surface
lacking
known
landmarks.
Input
for
the
function
is
either
a
matrix
of
vertex
coordinates
defining
a
3D
surface
object
or
a
mesh3d
object
as
obtained
from
read.ply().
Function:
digitsurface(spec, fixed, ptsize = 1, center = TRUE)
Arguments:
spec
Name
of
surface
file,
as
either
an
object
of
class
shape3d/mesh3d,
or
matrix
of
three-‐dimensional
vertex
coordinates.
fixed
Either:
a
single
value
designating
the
number
of
fixed
template
landmarks
to
be
selected
by
digit.fixed,
OR
a
p-‐x-‐k
matrix
of
3D
coordinates
collected
previously
(e.g.
in
other
software)
ptsize
numeric:
Size
to
plot
the
mesh
points
(vertices),
e.g.,
0.1
for
dense
meshes,
3
for
sparse
meshes
center
Logical
Whether
the
object
'spec'
should
be
centered
prior
to
digitizing
(default
center=TRUE)
Function
for
digitizing
fixed
3D
landmarks
and
placing
"surface
sliders",
semilandmarks
that
slide
over
a
surface.
Following
selection
of
fixed
points
(see
digitizing
below),
function
finds
surface
semilandmarks
following
algorithm
outlined
in
Gunz
et
al.
(2005)
and
Mitteroecker
and
Gunz
(2009).
digitsurface
finds
the
same
number
of
surface
semilandmarks
as
the
“template.txt”
file
(created
by
buildtemplate())
by
downsampling
scanned
mesh,
registering
template
with
current
specimen
via
GPA.
A
nearest
neighbor
algorithm
is
used
to
match
template
surface
landmarks
to
current
specimen's.
To
use
function
digitsurface,
the
template
must
be
constructed
first,
and
“template.txt”
be
in
the
working
directory.
Some
of
the
"fixed"
landmarks
digitized
with
digitsurface
can
be
later
designated
as
"curve
sliders"
using
function
define.sliders()
if
required
(see
details
in
digit.fixed).
NOTE:
Function
centers
the
mesh
before
digitizing
by
default
(center=TRUE).
If
one
chooses
not
to
center,
specimen
may
be
difficult
to
manipulate
in
rgl
window.
Digitizing:
as
before
in
digit.fixed().
Example,
digitizing
16
landmarks
on
a
mesh
and
fit
a
template
to
add
150
surface
sliding
semilandmarks
> myply2 <- read.ply("myply2.ply", ShowSpecimen=FALSE)
> digitsurface(myply2, fixed=16, pysize=1
Select Landmark 1
Keep Landmark 1(y/n)?
y
...
Select
all
of
the
fixed
landmarks,
and
then
the
function
will
calculate
the
position
of
the
surface
sliding
landmarks
on
the
mesh
based
on
the
template
(blue),
and
plot
them
in
green.
95
Function
writes
to
the
working
directory
an
NTS
file
with
the
name
of
the
specimen
and
.nts
suffix
containing
the
landmark
coordinates.
myply2.nts
"myply2
1 166 3 0 dim=3
13.6450089578878 9.85741717491749 -3.49156546534654
9.70490895788779 18.3504171749175 -1.90256546534653
-2.33683104211221 17.5362171749175 0.855334534653466
-14.1518710421122 15.2515171749175 1.06203453465347
-14.1681010421122 6.40941717491749 0.853034534653467
...
YouTube
video
of
this
function
in
action
here:
http://youtu.be/4S8XcMMgUyw
AUTO
mode:
The
function
as
described
above
(for
interactive
mode)
calls
digit.fixed(),
prompting
the
user
to
select
fixed
landmarks
in
the
rgl
window.
However
if
the
user
has
digitized
these
fixed
landmark
elsewhere
(e.g.,
in
other
software),
then
the
input
for
parameter
'fixed'
can
be
a
p-‐x-‐k
matrix
of
3D
coordinates.
In
this
case,
the
function
will
automatically
use
these
landmarks
and
fit
the
template
of
sliding
semilandmarks.
96
5.6 Calculate
semilandmarks
along
a
curve
(digit.curves)
A
function
to
calculate
equidistant
two-‐dimensional
and
three-‐dimensional
semilandmarks
along
a
curve.
These
landmarks
will
be
treated
as
"sliders"
in
Generalized
Procrustes
analysis
gpagen.
This
type
of
semilandmark
"slides"
along
curves
lacking
known
landmarks
(see
Bookstein
1997
for
algorithm
details).
Each
sliding
semilandmark
("sliders")
will
slide
between
two
designated
points,
along
a
line
tangent
to
the
specified
curvature,
as
specified
by
define.sliders.
Function:
digit.curves(start, curve, nPoints, closed=TRUE)
Arguments:
start
A
vector
of
coordinates
for
the
fixed
landmark
defining
the
start
of
the
curve
curve
A
p-‐x-‐k
matrix
of
2D
or
3D
coordinates
for
a
set
of
ordered
points
defining
a
curve
nPoints
Numeric
how
many
semilandmarks
to
place
equidistantly
along
the
curve
closed
Logical
Whether
the
curve
is
closed
(TRUE)
or
open
(FALSE)
The
function
is
based
upon
tpsDig2
'resample
curve
by
length'
for
2D
data
by
James
Rohlf.
The
start
of
the
curve
is
a
fixed
landmark
on
the
curve
that
is
equivalent
(homologous)
in
each
specimen
in
the
sample
(and
will
be
treated
as
a
fixed
point
during
Procrustes
Superimposition
using
gpagen).
Then
nPoints
are
calculated
along
the
curve
at
equidistant
points
from
the
start
to
the
end.
'curve'
is
a
p-‐x-‐k
matrix
of
2D
or
3D
coordinates
for
a
set
of
ordered
points
defining
a
curve.
This
can
be
the
pixels
of
an
outline
calculated
in
ImageJ
(save
xy
coordinates),
or
obtained
by
automatically
thresholding
a
jpeg
using
Momocs
import_jpg
function
(https://github.com/vbonhomme/Momocs/),
or
any
other
reasonable
way
of
obtaining
ordered
coordinates
along
a
curve
(including
sampling
by
hand
using
digit.fixed
or
digitize2d
-‐
but
note
that
there
should
be
more
points
defining
the
curve
than
nPoints
in
order
to
accurately
calculate
the
semilandmarks).
If
'closed
=
T',
the
function
returns
the
coordinates
of
the
'start'
landmark
plus
nPoints.
If
'closed
=
F',
the
function
returns
the
coordinates
of
the
'start'
landmark,
plus
nPoints
and
the
end
of
the
curve.
Example.
Here
we
have
an
outline
of
a
leaf,
exported
as
a
.txt
file
of
x,y,
coordinates
from
ImageJ
(see
warpRefOutline() for
details
on
how
this
can
be
done).
97
> lmks <- digit.curves(start, curve, nPoints=20, closed = T)
> points(lmks[,1], lmks[,2], pch=19, cex=0.5, col="green")
> lmks
[,1] [,2]
[1,] 8.5143 11.8367
[2,] 9.4671 11.2816
[3,] 10.3347 10.5267
[4,] 11.1673 9.7204
[5,] 11.9918 8.9059
[6,] 12.8146 8.0898
[7,] 13.6082 7.2609
[8,] 14.3863 6.4327
[9,] 15.1347 5.5750
[10,] 15.8599 4.6939
[11,] 16.5762 3.8367
[12,] 16.5224 3.7333
[13,] 15.6810 4.4980
[14,] 14.8422 5.2653
[15,] 14.0000 6.0294
[16,] 13.1725 6.8082
[17,] 12.3579 7.6163
[18,] 11.5347 8.4156
[19,] 10.7045 9.2082
[20,] 9.8901 10.0327
[21,] 9.1102 10.8917
98
Frequently
Asked
Questions
1) I’ve
loaded
my
TPS
file
but
I
get
a
warning
that
no
names
were
extracted.
My
TPS
file
has
specimen
names
in
it,
what
do
I
do?
-‐
For
TPS
files
it
is
necessary
to
specify
whether
the
specimen
name
should
be
read
from
the
“ID=”
line
or
the
“IMAGE=”
line.
See
section
1.1
for
more
details.
2) I
want
to
add
a
groups
to
my
data
analysis,
what
do
I
do?
-‐
Grouping
variables
can
be
made
in
R
(e.g.,
c())
or
imported
from
outside
(e.g.,
as
a
.csv
file).
See
section
2.4
for
more
details.
3) How
many
iterations
should
I
use
in
permutation
tests?
-‐
The
default
for
geomorph
functions
is
often
999.
Generally
more
is
better,
but
too
many
can
be
excessive
and
does
not
lead
to
more
power.
See
section
on
permutation
tests
in
the
introduction
for
more
details.
4) How
do
I
obtain
allometry
residuals
for
further
analyses
in
geomorph?
-‐
In
short,
you
don’t.
Instead,
include
size
as
a
covariate.
Reason:
MANCOVA
is
correct,
MANOVA
on
residuals
may
not
be
(if
different
slopes
then
residuals
from
common
slope
not
correct,
or
if
one
uses
residuals
on
each
group
separately
then
they
are
no
longer
comparable).
5) How
do
I
reflect
my
specimens
before
using
gpagen()
or
bilat.symmetry()?
-‐
Reflecting
a
set
of
specimens
may
be
accomplished
by
multiplying
one
coordinate
dimension
by
'-‐1'
for
these
structures
(either
the
x-‐,
the
y-‐,
or
the
z-‐dimension).
To
do
this:
> mydata # this is your 3D array of raw variables needing to be reflected
> refl <- array(1, dim=dim(mydata)) # make an array the same dimensions as mydata
and fill it with 1s
> refl[,1,] <- -1 # replace the x coordinate column with -1
> mydata <- mydata * refl # multiply the two arrays to reflect
6) I’ve
loaded
my
TPS
file
and
I
got
a
warning
that
“Not
all
specimens
have
scale...”.
I
defined
a
scale
by
digitizing
two
landmarks
on
the
scale
bar,
what
do
I
do?
-‐
Let’s
say
that
landmarks
47
and
48
define
the
ends
of
the
10mm
scale
bar,
and
coords
is
a
3D
array
of
the
raw
coordinate
data:
> for (i in 1:dim(coords)[3]){
scb <- coords[47:48,,i]
scale <- sqrt((scb[1,1]-scb[2,1])^2+(scb[1,2]-scb[2,2])^2)/1000
coords[,,i] <- coords[,,i]*scale }
> coords <- coords[-(47:48),,] # remove the landmarks
99
References
Adams, D. C. 1999. Methods for shape analysis of landmark data from articulated structures. Evol. Ecol. Res. 1:959-
970.
Adams, D. C. 2014a. A generalized K statistic for estimating phylogenetic signal from shape and other high-
dimensional multivariate data. Syst. Biol. 63:685-697.
---. 2014b. A method for assessing phylogenetic least squares models for shape and other high-dimensional
multivariate data. Evolution 68:2675-2688.
---. 2014c. Quantifying and comparing phylogenetic evolutionary rates for shape and other high-dimensional
phenotypic data. Syst. Biol. 63:166-177.
Adams, D. C., and C. D. Anthony. 1996. Using randomization techniques to analyse behavioural data. Anim. Behav.
51:733-738.
Adams, D. C., and M. M. Cerney. 2007. Quantifying biomechanical motion using Procrustes Motion Analysis. J.
Biomech. 40:437-444.
Adams, D. C., and M. L. Collyer. 2007. The analysis of character divergence along environmental gradients and other
covariates. Evolution 61:510-515.
---. 2009. A general framework for the analysis of phenotypic trajectories in evolutionary studies. Evolution 63:1143-
1154.
Adams, D. C., and R. Felice. 2014. Assessing phylogenetic morphological integration and trait covariation in
morphometric data using evolutionary covariance matrices. Plos ONE 9:e94335.
Adams, D. C., and A. Nistri. 2010. Ontogenetic convergence and evolution of foot morphology in European cave
salamanders (Family: Plethodontidae). BMC Evol. Biol. 10:216.
Adams, D. C., F. J. Rohlf, and D. E. Slice. 2004. Geometric morphometrics: ten years of progress following the
'revolution'. Italian Journal of Zoology 71:5-16.
Adams, D. C., F. J. Rohlf, and D. E. Slice. 2013. A field comes of age: geometric morphometrics in the 21st century.
Hystrix 24:7-14.
Anderson, M. J. 2001. A new method for non-parametric multivariate analysis of variance. Austral. Ecol. 26:32-46.
Anderson, M. J., and C. J. F. terBraak. 2003. Permutation tests for multi-factorial analysis of variance. Journal of
Statistical Computation and Simulation 73:85-113.
Blomberg, S. P., T. Garland, and A. R. Ives. 2003. Testing for phylogenetic signal in comparative data: behavioral
traits are more labile. Evolution 57:717-745.
Bookstein, F. L. 1991. Morphometric tools for landmark data: Geometry and Biology. Cambridge Univ. Press,, New
York.
Bookstein, F. L. 1997. Shape and the information in medical images: A decade of the morphometric synthesis.
Computer Vision and Image Understanding 66:97-118.
---. 2015. Integration, disintegration, and self-similarity: Characterizing the scales of shape variaiton in landmark data.
Evol. Biol.
Bookstein, F. L., P. Gunz, P. Mitteroecker, H. Prossinger, K. Schaefer, and H. Seidler. 2003. Cranial integration in
Homo: singular warps analysis of the midsagittal plane in ontogeny and evolution. J. Hum. Evol. 44:167-187.
Claude, J. 2008. Morphometrics with R. Springer.
Collyer, M. L., and D. C. Adams. 2007. Analysis of two-state multivariate phenotypic change in ecological studies.
Ecology 88:683-692.
---. 2013. Phenotypic trajectory analysis: comparison of shape change patterns in evolution and ecology. Hystrix 24:75-
83.
Collyer, M. L., D. J. Sekora, and D. C. Adams. 2014. A method for analysis of phenotypic change for phenotypes
described by high-dimensional data. Heredity 113.
Drake, A. G., and C. P. Klingenberg. 2008. The pace of morphological change: historical transformation of skull shape
in St Bernard dogs. Proc. R. Soc. B 275:71-76.
Dryden, I. L., and K. V. Mardia. 1993. Multivariate shape analysis. Sankhya 55:460--480.
Good, P. 2000. Permutation tests: a practical guide to resampling methods for testing hypotheses. Springer, New York.
Goodall, C. 1991. Procrustes methods in the statistical analysis of shape. Journal of the Royal Statistical Society. Series
B (Methodological):285-339.
Gower, J. C. 1975. Generalized Procrustes analysis. Psychometrika 40:33-51.
Gunz, P., P. Mitterocker, and F. L. Bookstein. 2005. Semilandmarks in three dimensions. Pp. 73-98 in D. E. Slice, ed.
Modern morphometrics in physical anthropology. Kluwer Academic/Plenum Publishers, New York.
100
Gunz, P., P. Mitteroecker, S. Neubauer, G. W. Weber, and F. L. Bookstein. 2009. Principles for the virtual
reconstruction of hominin crania. J. Hum. Evol. 57:48-62.
Kendall, D. G. 1984. Shape-manifolds, Procrustean metrics and complex projective spaces. Bulletin of the London
Mathematical Society 16:81-121.
Klingenberg, C. P. 2009. Morphometric integration and modularity in configurations of landmarks: tools for evaluating
a priori hypotheses. Evol. Dev. 11:405-421.
Klingenberg, C. P., M. Barluenga, and A. Meyer. 2002. Shape analysis of symmetric structures: quantifying variation
among individuals and asymmetry. Evolution 56:1909-1920.
Klingenberg, C. P., and N. A. Gidaszewski. 2010. Testing and quantifying phylogenetic signals and homoplasy in
morphometric data. Syst. Biol. 59:245-261.
Klingenberg, C. P., and G. S. McIntyre. 1998. Geometric morphometrics of developmental instability: Analyzing
patterns of fluctuating asymmetry with procrustes methods. Evolution 52:1363-1375.
Mardia, K. V., F. L. Bookstein, and I. J. Moreton. 2000. Statistical assessment of bilateral symmetry of shapes.
Biometrika 87:285-300.
Mitteroecker, P., and P. Gunz. 2009. Advances in Geometric Morphometrics. Evol. Biol. 36:235-247.
Mitteroecker, P., P. Gunz, M. Bernhard, K. Schaefer, and F. L. Bookstein. 2004. Comparison of cranial ontogenetic
trajectories among great apes and humans. J. Hum. Evol. 46:679-697.
O'Higgins, P., and N. Jones. 1998. Facial growth in Cercocebus torquatus: an application of three-dimensional
geometric morphometric techniques to the study of morphological variation. J. Anat. 193:251-272.
Revell, L. J. 2012. phytools: an R package for phylogenetic comparative biology (and other things). Methods in
Ecology and Evolution 3:217-223.
Rohlf, F. J. 1998. On applications of geometric morphometrics to studies of ontogeny and phylogeny. Syst. Biol.
47:147-158.
Rohlf, F. J. 1999. Shape statistics: Procrustes superimpositions and tangent spaces. J. Classif. 16:197-223.
Rohlf, F. J. 2002. Geometric morphometrics and phylogeny. Pp. 175-193 in N. MacLeod, and P. L. Forey, eds.
Morphology, shape and phylogeny. Francis & Taylor, London.
---. 2010. tpsRelw: Relative warp analysis. Version 1.49. Version 1.49. Department of Ecology and Evolution, State
University of New York at Stony Brook, Stony Brook, NY.
---. 2012. NTSYSpc: Numerical taxonomy and multivariate analysis system. Version 2.2. New York: Exeter Software.
Rohlf, F. J., and M. Corti. 2000. Use of two-block partial least-squares to study covariation in shape. Syst. Biol.
49:740-753.
Rohlf, F. J., and L. F. Marcus. 1993. A revolution in morphometrics. Trends Ecol. Evol. 8:129-132.
Rohlf, F. J., and D. Slice. 1990. Extensions of the Procrustes Method for the Optimal Superimposition of Landmarks.
Syst. Zool. 39:40-59.
Zelditch, M. L., D. L. Swiderski, and H. D. Sheets. 2012. Geometric morphometrics for biologists: a primer. 2nd ed.
Elsevier, Amsterdam.
101