In addition to reading in data digitized in StereoMorph
(see 01.1-Digitizing-Stereomorph) you may need to read in other types of
GM-related files, or other files containing information about your
specimens. Below are some basic instructions on how to do that.
Geomorph
has several built-in functions to read landmark
data files. Additionally, one can use standard IO functions in R to read
in a text file. Geomorph
also has the ability to digitize
2D or 3D data. For 3D, one can read in a 3D image in the form of a PLY
file.
In the previous lab, we learned how to digitize using
StereoMorph
. Here we take those datafiles and read them
into geomorph using the readShapes
function in
StereoMorph
combined with the readland.shapes
function in geomorph
. The result is an geomorphShapes
object which may be used in downstream GM analyses.
library(geomorph)
## Loading required package: RRPP
## Loading required package: rgl
## Loading required package: Matrix
library(StereoMorph)
myShapes <- readShapes("Data/Fish-Shapes-ex")
mydata <- readland.shapes(myShapes)
mydata$landmarks$Fish1
## [,1] [,2]
## LM1 4.524372 -5.382586
## LM2 7.711429 -3.899458
## LM3 10.806832 -4.399389
## LM4 11.052632 -5.661714
## LM5 8.898764 -6.369949
NA
, and can be estimated in
subsequent data-processing steps using
estimate.missing
.In addition to StereoMorph files, several other standard file formats are used to store GM data. Two of the more common file types are tps and nts files. These are text files that succinctly store landmark data in various types of matrices (open them in a text editor to gain simple understanding of the files). These were originally developed for the TPS series of software, and the statistics package NTSYS: hence their extension names. Geomorph provides functions to read in these type of files.
tps files have an inherent structure similar to the 3d-array data
structure used in geomorph; whereas nts files correspond to a structure
similar to two.d.arrays in geomorph. In both cases, data are read-in as
a 3d-array. You can open both types of files in a text editor to get
familiar with their structure. To read them into geomorph, use the
corresponding functions: readland.tps
and
readland.nts
.
mydata <- readland.tps("Data/salamanders.tps")
##
## No specID provided; specimens will be numbered 1, 2, 3 ...
##
## No curves detected; all points appear to be fixed landmarks.
str(mydata)
## num [1:12, 1:2, 1:287] 8.82 9.29 5.24 2.17 1.91 ...
## - attr(*, "dimnames")=List of 3
## ..$ : NULL
## ..$ : NULL
## ..$ : chr [1:287] "1" "2" "3" "4" ...
dim(mydata) # file contains 287 specimens with 12 landmarks each of 2D data
## [1] 12 2 287
mydata[,,1]
## [,1] [,2]
## [1,] 8.818432 53.14680
## [2,] 9.290848 52.18228
## [3,] 5.235944 53.00901
## [4,] 2.165240 51.47366
## [5,] 1.909348 51.70987
## [6,] 1.810928 51.80829
## [7,] 1.102304 52.83186
## [8,] 3.110072 54.48531
## [9,] 6.023304 54.44594
## [10,] 8.916852 54.60342
## [11,] 10.649044 54.83962
## [12,] 14.015008 52.93028
mydata <- readland.tps("Data/salamanders.tps", specID="imageID") # Specify specimen labels
##
## No curves detected; all points appear to be fixed landmarks.
str(mydata)
## num [1:12, 1:2, 1:287] 8.82 9.29 5.24 2.17 1.91 ...
## - attr(*, "dimnames")=List of 3
## ..$ : NULL
## ..$ : NULL
## ..$ : chr [1:287] "USNM170655l " "USNM170656l " "USNM170657l " "USNM182599l " ...
mydata[,,1:2]
## , , USNM170655l
##
## [,1] [,2]
## [1,] 8.818432 53.14680
## [2,] 9.290848 52.18228
## [3,] 5.235944 53.00901
## [4,] 2.165240 51.47366
## [5,] 1.909348 51.70987
## [6,] 1.810928 51.80829
## [7,] 1.102304 52.83186
## [8,] 3.110072 54.48531
## [9,] 6.023304 54.44594
## [10,] 8.916852 54.60342
## [11,] 10.649044 54.83962
## [12,] 14.015008 52.93028
##
## , , USNM170656l
##
## [,1] [,2]
## [1,] 8.89372 53.77644
## [2,] 9.26840 52.77072
## [3,] 5.56104 54.21028
## [4,] 1.87340 52.75100
## [5,] 1.28180 53.18484
## [6,] 1.24236 53.32288
## [7,] 0.84796 54.70328
## [8,] 3.35240 55.76816
## [9,] 6.29068 55.70900
## [10,] 8.87400 55.25544
## [11,] 10.74740 55.43292
## [12,] 14.39560 52.75100
readland.tps
will prompt the user to determine whether the
negative values are actual landmark coordinates, or whether they
represent missing data. In the latter case, the landmark values will be
replaced with NA
, and can be estimated in subsequent
data-processing steps using estimate.missing
.mydata <- readland.nts("Data/RATS.nts")
str(mydata)
## num [1:8, 1:2, 1:164] -0.45 -0.59 -0.515 -0.33 0 0.145 -0.045 -0.26 -0.475 -0.28 ...
mydata[,,1]
## [,1] [,2]
## [1,] -0.450 -0.475
## [2,] -0.590 -0.280
## [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
Another file type that is sometimes encountered is a Morphologika
file; developed for the Morphologika package. One can read these files
using geomorph
also, using the function
read.morphologika
:
mydata <- read.morphologika("Data/mophologikaexample.txt")
str(mydata)
## List of 4
## $ coords : num [1:31, 1:3, 1:15] 16 15 15 16.3 15.9 ...
## ..- attr(*, "dimnames")=List of 3
## .. ..$ : NULL
## .. ..$ : NULL
## .. ..$ : chr [1:15] "Specimen 1" "Specimen 2" "Specimen 3" "Specimen 4" ...
## $ labels : chr [1:15, 1] "Female" "Female" "Female" "Female" ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:15] "Specimen 1" "Specimen 2" "Specimen 3" "Specimen 4" ...
## .. ..$ : chr "Sex"
## $ wireframe: num [1:40, 1:2] 1 22 6 24 15 15 17 15 5 23 ...
## $ polygon : num [1:37, 1:3] 7 8 9 9 6 11 10 11 13 12 ...
dim(mydata$coords)
## [1] 31 3 15
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
## [7,] 18.22 23.65 11.12
## [8,] 18.77 23.75 11.21
## [9,] 18.72 24.24 11.62
## [10,] 19.26 25.71 10.33
## [11,] 18.21 25.39 12.05
## [12,] 19.32 25.91 14.39
## [13,] 17.45 26.36 13.70
## [14,] 14.51 26.93 11.50
## [15,] 15.93 26.94 12.36
## [16,] 17.11 26.94 13.63
## [17,] 18.69 26.98 14.67
## [18,] 19.50 27.03 15.03
## [19,] 15.75 29.67 10.89
## [20,] 14.96 29.08 11.07
## [21,] 14.92 28.36 11.48
## [22,] 15.85 29.43 11.37
## [23,] 15.93 27.16 12.02
## [24,] 17.07 28.57 12.32
## [25,] 17.90 30.15 11.26
## [26,] 18.62 30.00 11.18
## [27,] 18.69 29.71 11.45
## [28,] 19.14 28.53 10.28
## [29,] 18.17 28.51 12.08
## [30,] 19.25 28.15 14.23
## [31,] 17.48 27.52 13.71
Sometimes, we may wish to digitize directly from 3D images. These
come in the form of ply files, and geomorph
has the ability
to read, and then digitize such images.
new <- read.ply("Data/Mandible.ply")
str(new)
## List of 5
## $ vb : num [1:4, 1:24700] -3.722 -1.233 -0.206 1 -0.368 ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:4] "xpts" "ypts" "zpts" ""
## .. ..$ : NULL
## $ it : num [1:3, 1:50000] 17647 1 17626 21593 2 ...
## $ primitivetype: chr "triangle"
## $ material : NULL
## $ normals : num [1:4, 1:24700] 0.3506 0.0769 -0.9334 1 -0.7159 ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:4] "xpts" "ypts" "zpts" ""
## .. ..$ : NULL
## - attr(*, "class")= chr [1:2] "mesh3d" "shape3d"
Finally, one may have additional data, covariates, or other specimen
information that one wishes to read into R for downstream analyses. As
we are working in the R environment, one is free to do so using a
variety of read
functions. Below we provide an example for
a data matrix, and a phylogeny:
food <- read.csv("Data/food.csv", header=TRUE, row.names=1)
str(food)
## 'data.frame': 69 obs. of 16 variables:
## $ oligoch : num -0.334 -0.334 -0.334 -0.334 -0.334 ...
## $ gastrop : num -0.212 -0.212 -0.212 -0.212 -0.212 ...
## $ isopoda : num -0.374 3.082 -0.374 -0.374 -0.374 ...
## $ diplop : num -0.246 4.002 -0.246 -0.246 -0.246 ...
## $ chilop : num -0.277 -0.277 3.552 -0.277 -0.277 ...
## $ acar : num 0.204 -0.501 -0.501 0.204 -0.501 ...
## $ araneida: num -0.374 -0.374 -0.374 2.17 -0.374 ...
## $ chelon : num -0.309 -0.309 -0.309 -0.309 -0.309 ...
## $ coleopt : num 0.718 0.392 -1.391 0.718 0.864 ...
## $ collemb : num -0.374 -0.374 -0.374 -0.374 -0.374 ...
## $ diptera : num -0.324 1.916 4.155 2.843 -0.324 ...
## $ hymen : num 0.935 -0.3 0.935 1.663 -0.7 ...
## $ isopt : num -0.245 -0.245 -0.245 -0.245 -0.245 ...
## $ orthopt : num -0.273 -0.273 -0.273 2.959 -0.273 ...
## $ larvae : num -0.645 0.873 -0.645 -0.645 3.646 ...
## $ eggs : num -0.12 -0.12 -0.12 -0.12 -0.12 ...
food[1:2,]
## oligoch gastrop isopoda diplop chilop acar araneida
## 1 -0.333567 -0.2116501 -0.3740649 -0.2462653 -0.2774757 0.2035222 -0.3740685
## 2 -0.333567 -0.2116501 3.0823626 4.0018112 -0.2774757 -0.5007004 -0.3740685
## chelon coleopt collemb diptera hymen isopt orthopt
## 1 -0.3089659 0.7184250 -0.3735963 -0.3237473 0.9348487 -0.2453637 -0.2730511
## 2 -0.3089659 0.3918134 -0.3735963 1.9157772 -0.3004958 -0.2453637 -0.2730511
## larvae eggs
## 1 -0.6445006 -0.1203859
## 2 0.8725555 -0.1203859
library(ape)
mytree <- read.tree("Data/plethtree.tre")
plot(mytree)