This document aims to provide a quick introduction to morphometric analyses on fish outlines. The tutorial targets students and scientists in marine biology or ecology that have previous knowledge of the R software.

It is the companion tutorial for the article: Caillon F., Bonhomme V., Möllmann C., Frelat R. (2018). A morphometrics dive into fish morphology, Ecosphere 9(5): e02220 DOI: 10.1002/ecs2.2220. See the “Material and Methods” section of the paper and the “Electronic supplementary materials” for more details about the method.

Please visit Momocs speed dating for a detailed introduction to modern morphometrics with the R package Momocs.

The tutorial has been updated on 14th December 2020 with R 4.0.2 and Momocs v1.3.2.

Preliminaries

A simplified version of the dataset of fish outlines is included in the package Momocs (v > 1.2.2). The complete dataset can be downloaded here. Make sure the file CoralFishes.Rdata is in your working directory, then load it in R.

library(Momocs)
load("nsfishes.Rdata")
nsfishes
## Out (outlines)
##   - 218 outlines, 1523 +/- 423 coords (in $coo)
##   - 6 classifiers (in $fac): 
## # A tibble: 218 x 6
##   Species         Class        Superorder      Order       Family      Genus    
##   <fct>           <fct>        <fct>           <fct>       <fct>       <fct>    
## 1 Echiichthys vi… Actinoptery… Acanthopterygii Perciformes Trachinidae Echiicht…
## 2 Alosa alosa     Actinoptery… Clupeomorpha    Clupeiform… Clupeidae   Alosa    
## 3 Alosa fallax    Actinoptery… Clupeomorpha    Clupeiform… Clupeidae   Alosa    
## 4 Anarhichas lup… Actinoptery… Acanthopterygii Perciformes Anarhichad… Anarhich…
## 5 Atherina presb… Actinoptery… Acanthopterygii Atherinifo… Atherinidae Atherina 
## 6 Brosme brosme   Actinoptery… Paracanthopter… Gadiformes  Gadidae     Brosme   
## # … with 212 more rows
##   - also: $ldk

If you get an error message, check that the R package Momocs is installed correctly. If not, use the command: install.packages("Momocs").

The object nsfishes contains the outline of 218 images of fish (stored in the attribute coo), with 5 landmarks per image (stored in the attribute ldk) and taxonomic information about each image (stored in the attribute fac).

Visualization of the entire dataset

We can obtain a family picture of the 218 outlines with:

panel(nsfishes, col="grey")

Normalization of the raw outlines

A common problem in morphometrics is how to remove the information of size and rotation from the form of the outlines and retain only the shape.

Here, we chose to normalize outlines using a full generalized Procrustes adjustment based on the five landmarks: (1) ventral insertion of the caudal fin; (2) insertion of the pelvic fin, (3) snout tip; (4) anterior insertion of the dorsal fin; (5) dorsal insertion of the caudal fin. The third landmark (snout tip) is used as the starting point of the outline.

The alignment is made by, first, selecting the snout tip as starting point of the outlines (with coo_slide()) and, second, calculate the full Procrustes superimposition with the 5 landmarks (with fgProcrustes()).

fish_out <- nsfishes %>% coo_slide(ldk = 3) %>% fgProcrustes()

We now have aligned outlines stored in the object fish_out, and can visualize them with:

stack(fish_out) # or pile(fish_out, trans=0.9) %>% draw_centroid

Elliptical Fourier transforms

The mathematics behind elliptical Fourier transforms (EFT) are detailed in Bonhomme et al. 2014, Journal of Statistical Software. The main idea of EFT is to consider the outline as two periodic functions in x and y, that can be decomposed by Fourier transforms, as illustrated in the figure below.

osc <- coo_oscillo(fish_out[17], "efourier")
## Warning: `data_frame()` is deprecated as of tibble 1.1.0.
## Please use `tibble()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_warnings()` to see where this warning was generated.

The progressive capture of shape geometry along the number of harmonics can be visualized with:

calibrate_reconstructions_efourier(fish_out, id = 17, 
                          range = c(1, 2, 4, 8, 14, 20))

The number of harmonics to be kept for further analysis can be estimated with the cumulated harmonic power. Here, 14 harmonics were enough to gather 99% of the cumulated harmonic power along the dataset.

hpow <- calibrate_harmonicpower_efourier(fish_out, nb.h=30)
boxplot(hpow$q)

print(hpow$minh)
##   90%   95%   99% 99.9% 
##     7     8    14    24

Finally, we perform the EFT with efourier, keeping only 14 harmonics (nb.h = 14) and without normalization (norm = FALSE) because the outlines were aligned with Procrustes superimposition in the previous step:

fish_efa <- efourier(fish_out, norm = FALSE, nb.h = 14)

Multivariate analyses

From the harmonic coefficient on the 14 harmonics, we can calculate a principal component analysis (PCA) and visualize it with:

fish_pca <- PCA(fish_efa)
plot(fish_pca)

The grey shapes are theoretical shapes regularly drawn on the factorial plane. Looking at the variation of shapes along the principal components can help their interpretation. We can visualize the contribution of the three first Principal Components:

PCcontrib(fish_pca,nax = 1:3)

The first component describes the elongation of the body, the second component highlights the development of the pelvic fin, and the third component is about the shape of the dorsal and caudal fins.