Following includes codes used to do shape analysis of duck bones and then run phyloacc-c
We combined surface scans and CT/μCT scans to create a database of skeletal elements for three hindlimb bones (femur, tibiotarsus, and tarsometatarsus) along with the four forelimb bone (humerus, radius, ulna, and carpometacarpus) for 65 species of ducks. Our sampling for the species and the bone scans for those species are presented in the following table.
| Images | Scientific_Name | Common_Name | Voucher_Info | Genomes_NCBI | Femur | Tibiotarsus | Tarsometatarsus | Humerus | Radius | Ulna | Carpometacarpus |
|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
Aix galericulata | Mandarin Duck | USNM 622444 | GCA_024635365.1 | X | X | X | X | X | X | X |
|
|
Aix sponsa | Wood Duck | MCZ:Orn:347504 | GCA_032270905.1 | X | X | X | X | X | X | X |
|
|
Amazonetta brasiliensis | Brazilian Teal | USNM 631047 | X | X | X | X | X | X | X | |
|
|
Anas acuta | Northern Pintail | MCZ:Orn:341895 | GCA_963932015.1 | X | X | X | ||||
|
|
Anas aucklandica | Auckland Islands Teal | UMZC:Vertebrates:12/Ana/42/a/8-10 | X | X | X | X | X | X | X | |
|
|
Anas crecca | Green-winged Teal | MCZ:Orn:347036 | X | X | X | X | X | |||
|
|
Anas erythrorhyncha | Red-billed Duck | NHMUK:Zoo:S/1952.1.159 | X | X | X | X | ||||
|
|
Anas laysanensis | Laysan Duck | MCZ:Orn:347544 | X | X | X | |||||
|
|
Anas platyrhynchos | Mallard | MCZ:Orn:347156 | GCA900411745.1 | X | X | X | X | X | X | X |
|
|
Anas rubripes | American Black Duck | MCZ:Orn:337845 | X | X | X | X | X | X | ||
|
|
Anas zonorhyncha | Eastern Spot-billed Duck | USNM 633481 | GCA_002224875.1 | X | X | X | X | X | X | X |
|
|
Anhima cornuta | Horned Screamer | MCZ:Orn:346993 | GCA_013399475.1 | X | X | X | X | X | X | |
|
|
Anser albifrons | Greater White-fronted Goose | NHMUK:Zoo:1895.2.6.8 | X | X | X | X | X | X | X | |
|
|
Anser caerulescens | Snow Goose | MCZ:Orn:341885 | X | X | X | X | X | X | ||
|
|
Anser cygnoides | Swan Goose | USNM 19637 | GCA_026259575.1 | X | X | X | X | X | ||
|
|
Anser erythropus | Lesser White-fronted Goose | MCZ:Orn:340330 | X | X | X | |||||
|
|
Anser fabalis | Taiga Bean-Goose | MCZ:Orn:340262 | GCA_002592135.1 | X | X | X | X | X | ||
|
|
Anser indicus | Bar-headed Goose | USNM 557494 | GCA_025583725.1 | X | X | X | X | X | X | |
|
|
Anseranas semipalmata | Magpie Goose | NHMUK:Zoo:1852.7.22.1 | GCA_013399115.1 | X | X | X | X | X | ||
|
|
Asarcornis scutulata | White-winged Duck | USNM 612610 | GCA_013398475.1 | X | X | X | X | X | X | X |
|
|
Aythya americana | Redhead | MCZ:Orn:346918 | X | X | X | X | X | X | ||
|
|
Aythya fuligula | Tufted Duck | USNM 641850 | GCA_009819795.1 | X | X | X | X | X | X | X |
|
|
Branta bernicla | Brant | MCZ:Orn:336993 | X | X | X | X | X | X | X | |
|
|
Branta canadensis | Canada Goose | MCZ:Orn:346738 | GCA_006130075.1 | X | X | X | X | X | X | X |
|
|
Branta leucopsis | Barnacle Goose | MCZ:Orn:346732 | X | X | X | X | X | X | X | |
|
|
Bucephala clangula | Common Goldeneye | MCZ:Orn:347155 | X | X | X | X | X | X | X | |
|
|
Cairina moschata | Muscovy Duck | MCZ:Orn:348425 | GCA_018104995.1 | X | X | X | X | X | X | |
|
|
Cereopsis novaehollandiae | Cape Barren Goose | MCZ:Orn:347095 | X | X | X | X | X | X | X | |
|
|
Chauna chavaria | Northern Screamer | MCZ:Orn:340307 | X | X | X | X | ||||
|
|
Chenonetta jubata | Maned Duck | MCZ:Orn:339522 | X | X | X | |||||
|
|
Chloephaga hybrida | Kelp Goose | MCZ:Orn:340225 | X | X | X | X | X | X | ||
|
|
Chloephaga picta | Upland Goose | MCZ:Orn:342847 | X | X | X | X | ||||
|
|
Chloephaga poliocephala | Ashy-headed Goose | NHMUK:Zoo:S/1963.10.1 | X | X | X | X | X | X | ||
|
|
Chloephaga rubidiceps | Ruddy-headed Goose | MCZ:Orn:343209 | X | X | X | X | X | X | ||
|
|
Clangula hyemalis | Long-tailed Duck | MCZ:Orn:346497 | GCA_029619115.1 | X | X | X | X | X | ||
|
|
Cygnus columbianus | Tundra Swan | MCZ:Orn:343048 | X | X | X | X | ||||
|
|
Cygnus olor | Mute Swan | NHMUK:Zoo:1854.6.25.2 | GCA_009769625.2 | X | X | X | X | X | X | X |
|
|
Dendrocygna autumnalis | Black-bellied Whistling-Duck | MCZ:Orn:335880 | X | X | X | X | X | X | X | |
|
|
Dendrocygna bicolor | Fulvous Whistling-Duck | MCZ:Orn:347071 | X | X | X | X | X | X | X | |
|
|
Heteronetta atricapilla | Black-headed Duck | NHMUK:Zoo:S/2002.47.6 | GCA_011075105.1 | X | X | X | X | X | X | |
|
|
Histrionicus histrionicus | Harlequin Duck | NHMUK:Zoo:1843.6.23.23 | X | X | X | X | X | X | ||
|
|
Lophodytes cucullatus | Hooded Merganser | MCZ:Orn:347140 | X | X | X | X | X | X | ||
|
|
Lophonetta specularioides | Crested Duck | USNM 490992 | GCA_032165235.1 | X | X | X | X | X | X | X |
|
|
Malacorhynchus membranaceus | Pink-eared Duck | USNM 553596 | X | X | X | X | X | X | X | |
|
|
Mareca strepera | Gadwall | MCZ:Orn:341872 | GCA_035583915.1 | X | X | X | X | X | ||
|
|
Mareca sibilatrix | Chiloe Wigeon | NHMUK:Zoo:S/1985.72.2 | GCA_034783215.1 | X | X | X | X | X | X | X |
|
|
Marmaronetta angustirostris | Marbled Teal | USNM 500299 | X | X | X | X | X | X | X | |
|
|
Melanitta fusca | Velvet Scoter | MCZ:Orn:348703 | GCA_029620185.1 | X | X | X | X | X | ||
|
|
Melanitta perspicillata | Surf Scoter | MCZ:Orn:347151 | X | X | X | X | X | |||
|
|
Merganetta armata | Torrent Duck | MCZ:Orn:345094 | X | X | X | X | X | X | X | |
|
|
Mergellus albellus | Smew | MCZ:Orn:348520 | X | X | X | X | X | X | X | |
|
|
Mergus merganser | Common Merganser | MCZ:Orn:340318 | X | X | ||||||
|
|
Mergus serrator | Red-breasted Merganser | MCZ:Orn:343636 | X | X | X | X | X | X | X | |
|
|
Nettapus auritus | African Pygmy-Goose | MCZ:Orn:341374 | GCA_011076525.1 | X | X | X | ||||
|
|
Oxyura jamaicensis | Ruddy Duck | NHMUK:Zoo:S/1985.70.4 | GCA_011077185.1 | X | X | X | X | X | X | |
|
|
Oxyura ferruginea | Andean Duck | MCZ:Orn:341437 | X | X | X | X | X | |||
|
|
Sarkidiornis melanotos | Knob-billed Duck | USNM 488140 | X | X | X | X | X | X | X | |
|
|
Somateria mollissima | Common Eider | MCZ:Orn:336958 | GCA_951411735.1 | X | X | X | X | X | X | |
|
|
Spatula clypeata | Northern Shoveler | MCZ:Orn:347105 | X | X | X | X | X | X | ||
|
|
Spatula discors | Blue-winged Teal | NHMUK:Zoo:S/2001.41.5 | GCA_032165275.1 | X | X | X | X | X | X | X |
|
|
Stictonetta naevosa | Freckled Duck | USNM 555594 | GCA_011074415.1 | X | X | X | X | X | X | X |
|
|
Tachyeres brachypterus | Falkland Steamer-Duck | MCZ:Orn:342206 | GCA_032357605.1 | X | X | X | X | X | X | X |
|
|
Tachyeres patachonicus | Flying Steamer-Duck | USNM 491013 | X | X | X | X | X | X | X | |
|
|
Tachyeres pteneres | Flightless Steamer-Duck | USNM 490930 | X | X | X | X | X | X | X | |
|
|
Tadorna tadorna | Common Shelduck | MCZ:Orn:347538 | X | X | X | X | X | X | X |
After all the scans were collected, all scans were roughly aligned at the same coordinate space using the Align function in Meshmixer. For CT scans, we removed any internal structure by using the Select function to select the outer surface (setting the Crease Angle Thres option to >70 that prevents the selection from moving to the internal surface through holes) and using the Invert function to switch to internal surface, which were then deleted. We used Make Solid function to close any holes on the outside mesh, with a comparable Solid Accuracy and Mesh Density to avoid over smoothing of scans. Finally we exported this scan as a .obj file.
For landmarking, we used the pseudolandmarking (Rolfe, Davis, and Maga 2021) approach implemented through PseudoLMGenerator function of SlicerMorph (Rolfe et al. 2021) in Slicer. We used the Mallard Duck (Anas platyrhynchos) for the reference specimen to generate the primary landmark for all bones except the tibiotarsus (where the mallard specimen lacks the fibula) where we used the closely related Spot-billed Duck (Anas zonorhyncha). Spacing tolerance for each bone was adjusted to apply ~400 pseudolandmarks per bone.
| Bone | Spatial Tolerance | Number of Pseudolandmarks | Point Density Adjustment |
|---|---|---|---|
| Femur | 2.7 | 459 | 1.7 |
| Tibiotarsus | 2.0 | 480 | 1.9 |
| Tarsometatarsus | 2.8 | 431 | 1.7 |
| Humerus | 2.4 | 458 | 1.9 |
| Radius | 1.8 | 432 | 2.6 |
| Ulna | 2.2 | 452 | 2.0 |
| Carpometacarpus | 2.6 | 432 | 2.6 |
To transfer pseudolanmarks from one species to another, we used the single-template ALPACA framework (Porto, Rolfe, and Maga 2021). We adjusted the point density adjustment to create meshes of ~4000 points as recommended for ALPACA (values in table above). We used a BCPD acceleration for processing the samples. We used a batch processing to generate landmarks for bones of all the species.
We used the phylogeny from () for this study. For a few taxa missing in the tree that we had scans for, we appended a branch next to the known closest relative species.
duck_data <- xlsx::read.xlsx("Ducks_MCZ.xlsx", sheetIndex = 1, header = T)
duck_data <- duck_data[-66,]
#get body size
duckbm <- log10(duck_data$Body.mass.g)
names(duckbm) <- duck_data$Scientific_Name
#get flight data
flight <- as.factor(duck_data$Flight)
names(flight) <- duck_data$Scientific_Name
flight
## Aix_galericulata Aix_sponsa
## 1 1
## Amazonetta_brasiliensis Anas_acuta
## 1 1
## Anas_aucklandica Anas_crecca
## 0 1
## Anas_erythrorhyncha Anas_laysanensis
## 1 1
## Anas_platyrhynchos Anas_rubripes
## 1 1
## Anas_zonorhyncha Anhima_cornuta
## 1 1
## Anser_albifrons Anser_caerulescens
## 1 1
## Anser_cygnoides Anser_erythropus
## 1 1
## Anser_fabalis Anser_indicus
## 1 1
## Anseranas_semipalmata Asarcornis_scutulata
## 1 1
## Aythya_americana Aythya_fuligula
## 1 1
## Branta_bernicla Branta_canadensis
## 1 1
## Branta_leucopsis Bucephala_clangula
## 1 1
## Cairina_moschata Cereopsis_novaehollandiae
## 1 1
## Chauna_chavaria Chenonetta_jubata
## 1 1
## Chloephaga_hybrida Chloephaga_picta
## 1 1
## Chloephaga_poliocephala Chloephaga_rubidiceps
## 1 1
## Clangula_hyemalis Cygnus_columbianus
## 1 1
## Cygnus_olor Dendrocygna_autumnalis
## 1 1
## Dendrocygna_bicolor Heteronetta_atricapilla
## 1 1
## Histrionicus_histrionicus Lophodytes_cucullatus
## 1 1
## Lophonetta_specularioides Malacorhynchus_membranaceus
## 1 1
## Mareca_strepera Mareca_sibilatrix
## 1 1
## Marmaronetta_angustirostris Melanitta_fusca
## 1 1
## Melanitta_perspicillata Merganetta_armata
## 1 1
## Mergellus_albellus Mergus_merganser
## 1 1
## Mergus_serrator Nettapus_auritus
## 1 1
## Oxyura_jamaicensis Oxyura_ferruginea
## 1 1
## Sarkidiornis_melanotos Somateria_mollissima
## 1 1
## Spatula_clypeata Spatula_discors
## 1 1
## Stictonetta_naevosa Tachyeres_brachypterus
## 1 0
## Tachyeres_patachonicus Tachyeres_pteneres
## 1 0
## Tadorna_tadorna
## 1
## Levels: 0 1
#get diving data
diving <- as.factor(duck_data$Diving)
names(diving) <- duck_data$Scientific_Name
diving
## Aix_galericulata Aix_sponsa
## Dabbling Dabbling
## Amazonetta_brasiliensis Anas_acuta
## Dabbling Occasional_diving
## Anas_aucklandica Anas_crecca
## Occasional_diving Dabbling
## Anas_erythrorhyncha Anas_laysanensis
## Dabbling Dabbling
## Anas_platyrhynchos Anas_rubripes
## Occasional_diving Diving
## Anas_zonorhyncha Anhima_cornuta
## Dabbling Walking
## Anser_albifrons Anser_caerulescens
## Walking Walking
## Anser_cygnoides Anser_erythropus
## Walking Surface_swimmer
## Anser_fabalis Anser_indicus
## Surface_swimmer Surface_swimmer
## Anseranas_semipalmata Asarcornis_scutulata
## Surface_swimmer Occasional_diving
## Aythya_americana Aythya_fuligula
## Diving Diving
## Branta_bernicla Branta_canadensis
## Dabbling Occasional_diving
## Branta_leucopsis Bucephala_clangula
## Surface_swimmer Diving
## Cairina_moschata Cereopsis_novaehollandiae
## Surface_swimmer Walking
## Chauna_chavaria Chenonetta_jubata
## Walking Surface_swimmer
## Chloephaga_hybrida Chloephaga_picta
## Surface_swimmer Walking
## Chloephaga_poliocephala Chloephaga_rubidiceps
## Walking Walking
## Clangula_hyemalis Cygnus_columbianus
## Diving Dabbling
## Cygnus_olor Dendrocygna_autumnalis
## Dabbling Dabbling
## Dendrocygna_bicolor Heteronetta_atricapilla
## Occasional_diving Diving
## Histrionicus_histrionicus Lophodytes_cucullatus
## Diving Diving
## Lophonetta_specularioides Malacorhynchus_membranaceus
## Dabbling Dabbling
## Mareca_strepera Mareca_sibilatrix
## Dabbling Dabbling
## Marmaronetta_angustirostris Melanitta_fusca
## Dabbling Diving
## Melanitta_perspicillata Merganetta_armata
## Diving Diving
## Mergellus_albellus Mergus_merganser
## Diving Diving
## Mergus_serrator Nettapus_auritus
## Diving Dabbling
## Oxyura_jamaicensis Oxyura_ferruginea
## Diving Diving
## Sarkidiornis_melanotos Somateria_mollissima
## Dabbling Diving
## Spatula_clypeata Spatula_discors
## Occasional_diving Dabbling
## Stictonetta_naevosa Tachyeres_brachypterus
## Dabbling Occasional_diving
## Tachyeres_patachonicus Tachyeres_pteneres
## Diving Occasional_diving
## Tadorna_tadorna
## Dabbling
## Levels: Dabbling Diving Occasional_diving Surface_swimmer Walking
duck_tree <- read.tree("duck_tree.tre")
# Root at the Anhimidae
duck_tree <- root(duck_tree, outgroup = c("Anhima_cornuta", "Chauna_chavaria", "Chauna_torquata"))
# Add missing species
duck_tree <- bind.tip(duck_tree, "Anas_aucklandica", where = which(duck_tree$tip.label=="Anas_chlorotis"), edge.length = 0.0143477498/4, position = 0.0143477498/4)
duck_tree <- bind.tip(duck_tree, "Anas_zonorhyncha", where = which(duck_tree$tip.label=="Anas_platyrhynchos"), edge.length = 0.0022507147/4, position = 0.0022507147/4)
duck_tree <- bind.tip(duck_tree, "Anser_erythropus", where = which(duck_tree$tip.label=="Anser_albifrons"), edge.length = 0.0017958047/4, position = 0.0017958047/4)
duck_tree <- bind.tip(duck_tree, "Asarcornis_scutulata", where = which(duck_tree$tip.label=="Cairina_moschata"), edge.length = 0.0067085060/4, position = 0.0067085060/4)
duck_tree$tip.label[which(duck_tree$tip.label == "Malacorhyncus_membranaceus")] <- "Malacorhynchus_membranaceus"
duck_tree <- bind.tip(duck_tree, "Mergus_merganser", where = which(duck_tree$tip.label=="Mergus_serrator"), edge.length = 0.0027206995/4, position = 0.0027206995/4)
duck_tree <- bind.tip(duck_tree, "Oxyura_ferruginea", where = which(duck_tree$tip.label=="Oxyura_jamaicensis"), edge.length = 0.0024525321/4, position = 0.0024525321/4)
duck_tree <- bind.tip(duck_tree, "Spatula_discors", where = which(duck_tree$tip.label=="Spatula_cyanoptera"), edge.length = 0.0027173372/4, position = 0.0027173372/4)
duck_tree <- bind.tip(duck_tree, "Anas_crecca", where = which(duck_tree$tip.label=="Anas_flavirostris"), edge.length = 0.0032631134/4, position = 0.0032631134/4)
duck_tree_orig <- duck_tree
To conduct a Generalized Procrustes Analysis we used the gpagen function of the geommorph package. We first summarized the information for all the specimens of a single bone using the GPA function in SlicerMorph to allow for easier upload into R work environment. For pca we used gm.prcomp with phylogeny from above.
# Load summarized data for all landmark files
logfile <- parser("gpa/Femur/analysis.log", forceLPS = T)
# Run GPA
femur.gpa <- gpagen(logfile$LM, print.progress = F)
femurshape <- femur.gpa$coords
dimnames(femurshape)[[3]] <- sub("^([^_]+_[^_]+).*", "\\1", dimnames(femurshape)[[3]])
femursize <- log10(femur.gpa$Csize)
names(femursize) <- dimnames(femurshape)[[3]]
# Subset phylogenetic tree to keep only taxa for which scans exist
duck_tree_femur <- keep.tip(duck_tree_orig, duck_data$Scientific_Name[duck_data$Femur %in% "X"])
dimnames(femur.gpa$coords)[[3]] <- unlist(lapply(str_split(dimnames(femur.gpa$coords)[[3]], "_"), FUN = function(x){paste(x[1], x[2], sep="_")}))
femur_pca <- gm.prcomp(femur.gpa$coords, phy = duck_tree_femur)
# pc1 (25.87%), pc2 (19.36%), pc3 (7.10%), pc4 (5.34%), pc5 (5.01%)
asp_ratio <- 1.618
duck_pca <- data.frame(species=names(femur_pca$x[,1]), PC1=femur_pca$x[,1], PC2=femur_pca$x[,2], PC3=femur_pca$x[,3])
duck_pca <- merge(duck_pca, duck_data[,c("Scientific_Name", "Images", "Femur")], by.x = "species", by.y = "Scientific_Name", all.x = T, all.y = F)
g1 <- ggplot(duck_pca, aes(PC1, PC2)) +
geom_image(aes(image=Images), size=0.075, by = "width", asp = asp_ratio)+
theme_classic()+
theme(aspect.ratio = 1/asp_ratio)
g1
Then we check for convergence
femurshape <- femurshape[,,duck_tree_femur$tip.label]
femursize <- femursize[duck_tree_femur$tip.label]
femurbm <- duckbm[duck_tree_femur$tip.label]
femflight <- flight[duck_tree_femur$tip.label]
femdiving <- diving[duck_tree_femur$tip.label]
femallom1 <- procD.pgls(femurshape ~ femurbm, phy = duck_tree_femur, SS.type = "II", iter = 999)
summary(femallom1)
femallom2 <- procD.pgls(femurshape ~ femursize, phy = duck_tree_femur,SS.type = "II", iter = 999)
summary(femallom2)
femallom3 <- procD.pgls(femurshape ~ femurbm + femursize, phy = duck_tree_femur, SS.type = "II", iter = 999)
summary(femallom3)
femur.mod <- procD.pgls(femurshape ~ femurbm + femursize + femdiving, phy = duck_tree_femur, SS.type = "II", iter = 999)
summary(femur.mod)
femur.mod <- procD.pgls(femurshape ~ femurbm + femursize + femdiving + femflight, phy = duck_tree_femur, SS.type = "II", iter = 999)
summary(femur.mod)
#convergence
### find convergence test for 3D data
femdivelist <- names(femdiving[femdiving == "Diving"])
femdivconv <- convrat(duck_tree_femur, femur_pca$x[,1:5], femdivelist)
femdivconvsig <- convratsig(duck_tree_femur, femur_pca$x[,1:5], femdivelist, 10)
femdivconvsig
## convergence in flightless ducks
femflightlesslist <- names(femflight[femflight == "0"])
femflightlessconv <- convrat(femurtree, femur_pca$x[,1:5], femflightlesslist)
femflightlessconv
femflightconvsig <- convratsig(femurtree, femur_pca$x[,1:5], femflightlesslist, 10)
femflightconvsig
## Convergence test with PC axes
femconv <- conv.map(femdivelist, scores = femur_pca$x, pcs = femur_pca$rotation, mshape = femurmean, focal = "Somateria_mollissima" )
femconvtest <- convnum(duck_tree_femur, femur_pca$x[,1:5], femdivelist)
We also generated warped meshes to visualize bone structure relevant to the different PC axes.
ref <- mshape(femur.gpa$coords)
ref_obj <- read.ply("Anas_platyrhynchos_MCZ347156_femur.ply", ShowSpecimen = F)
ref_lnd <- readland.fcsv("Anas_platyrhynchos_MCZ347156_femur_new.fcsv")
warped_ref <- warpRefMesh(ref_obj, ref_lnd, ref, color = "ivory", centered = FALSE)
g2 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$min, mesh=warped_ref, method = "surface")
g3 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$max, mesh=warped_ref, method = "surface")
g4 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$min, mesh=warped_ref, method = "surface")
g5 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$max, mesh=warped_ref, method = "surface")
mesh2ply(warped_ref, "femur_ref")
mesh2ply(g2, "femur_pc1_min")
mesh2ply(g3, "femur_pc1_max")
mesh2ply(g4, "femur_pc2_min")
mesh2ply(g5, "femur_pc2_max")
logfile <- parser("gpa/Tibiotarsus/analysis.log", forceLPS = T)
tibiotarsus.gpa <- gpagen(logfile$LM, print.progress = F)
tibioshape <- tibiotarsus.gpa$coords
dimnames(tibioshape)[[3]] <- sub("^([^_]+_[^_]+).*", "\\1", dimnames(tibioshape)[[3]])
tibiosize <- log10(tibiotarsus.gpa$Csize)
names(tibiosize) <- dimnames(tibioshape)[[3]]
duck_tree_tibio <- keep.tip(duck_tree_orig, duck_data$Scientific_Name[duck_data$Tibiotarsus %in% "X"])
dimnames(tibiotarsus.gpa$coords)[[3]] <- unlist(lapply(str_split(dimnames(tibiotarsus.gpa$coords)[[3]], "_"), FUN = function(x){paste(x[1], x[2], sep="_")}))
tibio_pca <- gm.prcomp(tibiotarsus.gpa$coords, phy = duck_tree_tibio)
# pc1 (29.38%), pc2 (11.31%), pc3 (10.16%), pc4 (7.18%), pc5 (4.51%)
asp_ratio <- 1.618
duck_pca <- data.frame(species=names(tibio_pca$x[,1]), PC1=tibio_pca$x[,1], PC2=tibio_pca$x[,2], PC3=tibio_pca$x[,3], PC4=tibio_pca$x[,4], PC5=tibio_pca$x[,5])
duck_pca <- merge(duck_pca, duck_data[,c("Scientific_Name", "Images", "Tibiotarsus")], by.x = "species", by.y = "Scientific_Name", all.x = T, all.y = F)
g1 <- ggplot(duck_pca, aes(PC1, PC3)) +
geom_image(aes(image=Images), size=0.075, by = "width", asp = asp_ratio)+
theme_classic()+
theme(aspect.ratio = 1/asp_ratio)
g1
Then we check for convergence
tibioshape <- tibioshape[,,duck_tree_tibio$tip.label]
tibiosize <- tibiosize[duck_tree_tibio$tip.label]
tibiobm <- duckbm[duck_tree_tibio$tip.label]
tibioflight <- flight[duck_tree_tibio$tip.label]
tibiodiving <- diving[duck_tree_tibio$tip.label]
tibioallom1 <- procD.pgls(tibioshape ~ tibiobm, phy = duck_tree_tibio, SS.type = "II", iter = 999)
summary(tibioallom1)
tibioallom2 <- procD.pgls(tibioshape ~ tibiosize, phy = duck_tree_tibio,SS.type = "II", iter = 999)
summary(tibioallom2)
tibioallom3 <- procD.pgls(tibioshape ~ tibiobm + tibiosize, phy = duck_tree_tibio, SS.type = "II", iter = 999)
summary(tibioallom3)
tibio.mod <- procD.pgls(tibioshape ~ tibiobm + tibiosize + tibiodiving, phy = duck_tree_tibio, SS.type = "II", iter = 999)
summary(tibio.mod)
tibio.mod <- procD.pgls(tibioshape ~ tibiobm + tibiosize + tibiodiving + tibioflight, phy = duck_tree_tibio, SS.type = "II", iter = 999)
summary(tibio.mod)
#convergence
### find convergence test for 3D data
tibiodivelist <- names(tibiodiving[tibiodiving == "Diving"])
tibiodivconv <- convrat(duck_tree_tibio, tibio_pca$x[,1:5], tibiodivelist)
tibiodivconvsig <- convratsig(duck_tree_tibio, tibio_pca$x[,1:5], tibiodivelist, 10)
tibiodivconvsig
## convergence in flightless ducks
tibioflightlesslist <- names(tibioflight[tibioflight == "0"])
tibioflightlessconv <- convrat(tibiotree, tibio_pca$x[,1:5], tibioflightlesslist)
tibioflightlessconv
tibioflightconvsig <- convratsig(tibiotree, tibio_pca$x[,1:5], tibioflightlesslist, 10)
tibioflightconvsig
## Convergence test with PC axes
tibioconv <- conv.map(tibiodivelist, scores = tibio_pca$x, pcs = tibio_pca$rotation, mshape = tibiomean, focal = "Somateria_mollissima" )
tibioconvtest <- convnum(duck_tree_tibio, tibio_pca$x[,1:5], tibiodivelist)
ref <- mshape(tibiotarsus.gpa$coords)
ref_obj <- read.ply("Anas_zonorhyncha_USNM633481_tibiotarsus.ply", ShowSpecimen = F)
ref_lnd <- readland.fcsv("Anas_zonorhyncha_USNM633481_tibiotarsus.fcsv")
warped_ref <- warpRefMesh(ref_obj, ref_lnd, ref, color = "ivory", centered = FALSE)
g2 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$min, mesh=warped_ref, method = "surface")
g3 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$max, mesh=warped_ref, method = "surface")
g4 <- plotRefToTarget(ref, pca$shapes$shapes.comp3$min, mesh=warped_ref, method = "surface")
g5 <- plotRefToTarget(ref, pca$shapes$shapes.comp3$max, mesh=warped_ref, method = "surface")
mesh2ply(warped_ref, "tibiotarsus_ref")
mesh2ply(g2, "tibiotarsus_pc1_min")
mesh2ply(g3, "tibiotarsus_pc1_max")
mesh2ply(g4, "tibiotarsus_pc3_min")
mesh2ply(g5, "tibiotarsus_pc3_max")
logfile <- parser("gpa/Tarsometatarsus/analysis.log", forceLPS = T)
tarsometatarsus.gpa <- gpagen(logfile$LM, print.progress = F)
tarsoshape <- tarsometatarsus.gpa$coords
dimnames(tarsoshape)[[3]] <- sub("^([^_]+_[^_]+).*", "\\1", dimnames(tarsoshape)[[3]])
tarsosize <- log10(tarsometatarsus.gpa$Csize)
names(tarsosize) <- dimnames(tarsoshape)[[3]]
duck_tree_tarso <- keep.tip(duck_tree_orig, duck_data$Scientific_Name[duck_data$Tarsometatarsus %in% "X"])
dimnames(tarsometatarsus.gpa$coords)[[3]] <- unlist(lapply(str_split(dimnames(tarsometatarsus.gpa$coords)[[3]], "_"), FUN = function(x){paste(x[1], x[2], sep="_")}))
tarso_pca <- gm.prcomp(tarsometatarsus.gpa$coords, phy = duck_tree_tarso)
# pc1 (40.49%), pc2 (10.91%), pc3 (7.74%), pc4 (5.44%), pc5 (4.45%)
asp_ratio <- 1.618
duck_pca <- data.frame(species=names(tarso_pca$x[,1]), PC1=tarso_pca$x[,1], PC2=tarso_pca$x[,2], PC3=tarso_pca$x[,3], PC4=tarso_pca$x[,4], PC5=tarso_pca$x[,5])
duck_pca <- merge(duck_pca, duck_data[,c("Scientific_Name", "Images", "Tarsometatarsus")], by.x = "species", by.y = "Scientific_Name", all.x = T, all.y = F)
g1 <- ggplot(duck_pca, aes(PC1, PC2)) +
geom_image(aes(image=Images), size=0.075, by = "width", asp = asp_ratio)+
theme_classic()+
theme(aspect.ratio = 1/asp_ratio)
g1
Then we check for convergence
tarsoshape <- tarsoshape[,,duck_tree_tarso$tip.label]
tarsosize <- tarsosize[duck_tree_tarso$tip.label]
tarsobm <- duckbm[duck_tree_tarso$tip.label]
tarsoflight <- flight[duck_tree_tarso$tip.label]
tarsodiving <- diving[duck_tree_tarso$tip.label]
tarsoallom1 <- procD.pgls(tarsoshape ~ tarsobm, phy = duck_tree_tarso, SS.type = "II", iter = 999)
summary(tarsoallom1)
tarsoallom2 <- procD.pgls(tarsoshape ~ tarsosize, phy = duck_tree_tarso,SS.type = "II", iter = 999)
summary(tarsoallom2)
tarsoallom3 <- procD.pgls(tarsoshape ~ tarsobm + tarsosize, phy = duck_tree_tarso, SS.type = "II", iter = 999)
summary(tarsoallom3)
tarso.mod <- procD.pgls(tarsoshape ~ tarsobm + tarsosize + tarsodiving, phy = duck_tree_tarso, SS.type = "II", iter = 999)
summary(tarso.mod)
tarso.mod <- procD.pgls(tarsoshape ~ tarsobm + tarsosize + tarsodiving + tarsoflight, phy = duck_tree_tarso, SS.type = "II", iter = 999)
summary(tarso.mod)
#convergence
### find convergence test for 3D data
tarsodivelist <- names(tarsodiving[tarsodiving == "Diving"])
tarsodivconv <- convrat(duck_tree_tarso, tarso_pca$x[,1:5], tarsodivelist)
tarsodivconvsig <- convratsig(duck_tree_tarso, tarso_pca$x[,1:5], tarsodivelist, 10)
tarsodivconvsig
## convergence in flightless ducks
tarsoflightlesslist <- names(tarsoflight[tarsoflight == "0"])
tarsoflightlessconv <- convrat(tarsotree, tarso_pca$x[,1:5], tarsoflightlesslist)
tarsoflightlessconv
tarsoflightconvsig <- convratsig(tarsotree, tarso_pca$x[,1:5], tarsoflightlesslist, 10)
tarsoflightconvsig
## Convergence test with PC axes
tarsoconv <- conv.map(tarsodivelist, scores = tarso_pca$x, pcs = tarso_pca$rotation, mshape = tarsomean, focal = "Somateria_mollissima" )
tarsoconvtest <- convnum(duck_tree_tarso, tarso_pca$x[,1:5], tarsodivelist)
ref <- mshape(tarsometatarsus.gpa$coords)
ref_obj <- read.ply("Anas_platyrhynchos_MCZ347156_tarsometatarsus.ply", ShowSpecimen = F)
ref_lnd <- readland.fcsv("Anas_platyrhynchos_MCZ347156_tarsometatarsus.fcsv")
warped_ref <- warpRefMesh(ref_obj, ref_lnd, ref, color = "ivory", centered = FALSE)
g2 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$min, mesh=warped_ref, method = "surface")
g3 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$max, mesh=warped_ref, method = "surface")
g4 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$min, mesh=warped_ref, method = "surface")
g5 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$max, mesh=warped_ref, method = "surface")
mesh2ply(warped_ref, "tarsometatarsus_ref")
mesh2ply(g2, "tarsometatarsus_pc1_min")
mesh2ply(g3, "tarsometatarsus_pc1_max")
mesh2ply(g4, "tarsometatarsus_pc2_min")
mesh2ply(g5, "tarsometatarsus_pc2_max")
logfile <- parser("gpa/Humerus/analysis.log", forceLPS = T)
humerus.gpa <- gpagen(logfile$LM, print.progress = F)
humershape <- humerus.gpa$coords
dimnames(humershape)[[3]] <- sub("^([^_]+_[^_]+).*", "\\1", dimnames(humershape)[[3]])
humersize <- log10(humerus.gpa$Csize)
names(humersize) <- dimnames(humershape)[[3]]
duck_tree_humer <- keep.tip(duck_tree_orig, duck_data$Scientific_Name[duck_data$Humerus %in% "X"])
duck_tree_humer <- root(duck_tree_humer, outgroup = c("Anhima_cornuta", "Chauna_chavaria"))
dimnames(humerus.gpa$coords)[[3]] <- unlist(lapply(str_split(dimnames(humerus.gpa$coords)[[3]], "_"), FUN = function(x){paste(x[1], x[2], sep="_")}))
humer_pca <- gm.prcomp(humerus.gpa$coords, phy = duck_tree_humer)
# pc1 (24.13%), pc2 (12.16%), pc3 (9.49%), pc4 (8.66%), pc5 (6.59%)
asp_ratio <- 1.618
duck_pca <- data.frame(species=names(humer_pca$x[,1]), PC1=humer_pca$x[,1], PC2=humer_pca$x[,2], PC3=humer_pca$x[,3])
duck_pca <- merge(duck_pca, duck_data[,c("Scientific_Name", "Images", "Humerus")], by.x = "species", by.y = "Scientific_Name", all.x = T, all.y = F)
g1 <- ggplot(duck_pca, aes(PC1, PC2)) +
geom_image(aes(image=Images), size=0.075, by = "width", asp = asp_ratio)+
theme_classic()+
theme(aspect.ratio = 1/asp_ratio)
g1
Then we check for convergence
humershape <- humershape[,,duck_tree_humer$tip.label]
humersize <- humersize[duck_tree_humer$tip.label]
humerbm <- duckbm[duck_tree_humer$tip.label]
humerflight <- flight[duck_tree_humer$tip.label]
humerdiving <- diving[duck_tree_humer$tip.label]
humerallom1 <- procD.pgls(humershape ~ humerbm, phy = duck_tree_humer, SS.type = "II", iter = 999)
summary(humerallom1)
humerallom2 <- procD.pgls(humershape ~ humersize, phy = duck_tree_humer,SS.type = "II", iter = 999)
summary(humerallom2)
humerallom3 <- procD.pgls(humershape ~ humerbm + humersize, phy = duck_tree_humer, SS.type = "II", iter = 999)
summary(humerallom3)
humer.mod <- procD.pgls(humershape ~ humerbm + humersize + humerdiving, phy = duck_tree_humer, SS.type = "II", iter = 999)
summary(humer.mod)
humer.mod <- procD.pgls(humershape ~ humerbm + humersize + humerdiving + humerflight, phy = duck_tree_humer, SS.type = "II", iter = 999)
summary(humer.mod)
#convergence
### find convergence test for 3D data
humerdivelist <- names(humerdiving[humerdiving == "Diving"])
humerdivconv <- convrat(duck_tree_humer, humer_pca$x[,1:5], humerdivelist)
humerdivconvsig <- convratsig(duck_tree_humer, humer_pca$x[,1:5], humerdivelist, 10)
humerdivconvsig
## convergence in flightless ducks
humerflightlesslist <- names(humerflight[humerflight == "0"])
humerflightlessconv <- convrat(humertree, humer_pca$x[,1:5], humerflightlesslist)
humerflightlessconv
humerflightconvsig <- convratsig(humertree, humer_pca$x[,1:5], humerflightlesslist, 10)
humerflightconvsig
## Convergence test with PC axes
humerconv <- conv.map(humerdivelist, scores = humer_pca$x, pcs = humer_pca$rotation, mshape = humermean, focal = "Somateria_mollissima" )
humerconvtest <- convnum(duck_tree_humer, humer_pca$x[,1:5], humerdivelist)
ref <- mshape(humerus.gpa$coords)
ref_obj <- read.ply("Anas_platyrhynchos_MCZ347156_humerus.ply", ShowSpecimen = F)
ref_lnd <- readland.fcsv("Anas_platyrhynchos_MCZ347156_humerus_new.fcsv")
warped_ref <- warpRefMesh(ref_obj, ref_lnd, ref, color = "ivory", centered = FALSE)
g2 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$min, mesh=warped_ref, method = "surface")
g3 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$max, mesh=warped_ref, method = "surface")
g4 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$min, mesh=warped_ref, method = "surface")
g5 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$max, mesh=warped_ref, method = "surface")
mesh2ply(warped_ref, "humerus_ref")
mesh2ply(g2, "humerus_pc1_min")
mesh2ply(g3, "humerus_pc1_max")
mesh2ply(g4, "humerus_pc2_min")
mesh2ply(g5, "humerus_pc2_max")
logfile <- parser("gpa/Radius/analysis.log", forceLPS = T)
radius.gpa <- gpagen(logfile$LM, print.progress = F)
radiishape <- radius.gpa$coords
dimnames(radiishape)[[3]] <- sub("^([^_]+_[^_]+).*", "\\1", dimnames(radiishape)[[3]])
radiisize <- log10(radius.gpa$Csize)
names(radiisize) <- dimnames(radiishape)[[3]]
duck_tree_radii <- keep.tip(duck_tree_orig, duck_data$Scientific_Name[duck_data$Radius %in% "X"])
dimnames(radius.gpa$coords)[[3]] <- unlist(lapply(str_split(dimnames(radius.gpa$coords)[[3]], "_"), FUN = function(x){paste(x[1], x[2], sep="_")}))
radii_pca <- gm.prcomp(radius.gpa$coords, phy = duck_tree_radii)
# pc1 (28.75%), pc2 (18.06%), pc3 (10.83%), pc4 (9.17%), pc5 (5.86%)
asp_ratio <- 1.618
duck_pca <- data.frame(species=names(radii_pca$x[,1]), PC1=radii_pca$x[,1], PC2=radii_pca$x[,2], PC3=radii_pca$x[,3], PC4=radii_pca$x[,4], PC5=radii_pca$x[,5])
duck_pca <- merge(duck_pca, duck_data[,c("Scientific_Name", "Images", "Radius")], by.x = "species", by.y = "Scientific_Name", all.x = T, all.y = F)
g1 <- ggplot(duck_pca, aes(PC1, PC2)) +
geom_image(aes(image=Images), size=0.075, by = "width", asp = asp_ratio)+
theme_classic()+
theme(aspect.ratio = 1/asp_ratio)
g1
Then we check for convergence
radiishape <- radiishape[,,duck_tree_radii$tip.label]
radiisize <- radiisize[duck_tree_radii$tip.label]
radiibm <- duckbm[duck_tree_radii$tip.label]
radiiflight <- flight[duck_tree_radii$tip.label]
radiidiving <- diving[duck_tree_radii$tip.label]
radiiallom1 <- procD.pgls(radiishape ~ radiibm, phy = duck_tree_radii, SS.type = "II", iter = 999)
summary(radiiallom1)
radiiallom2 <- procD.pgls(radiishape ~ radiisize, phy = duck_tree_radii,SS.type = "II", iter = 999)
summary(radiiallom2)
radiiallom3 <- procD.pgls(radiishape ~ radiibm + radiisize, phy = duck_tree_radii, SS.type = "II", iter = 999)
summary(radiiallom3)
radii.mod <- procD.pgls(radiishape ~ radiibm + radiisize + radiidiving, phy = duck_tree_radii, SS.type = "II", iter = 999)
summary(radii.mod)
radii.mod <- procD.pgls(radiishape ~ radiibm + radiisize + radiidiving + radiiflight, phy = duck_tree_radii, SS.type = "II", iter = 999)
summary(radii.mod)
#convergence
### find convergence test for 3D data
radiidivelist <- names(radiidiving[radiidiving == "Diving"])
radiidivconv <- convrat(duck_tree_radii, radii_pca$x[,1:5], radiidivelist)
radiidivconvsig <- convratsig(duck_tree_radii, radii_pca$x[,1:5], radiidivelist, 10)
radiidivconvsig
## convergence in flightless ducks
radiiflightlesslist <- names(radiiflight[radiiflight == "0"])
radiiflightlessconv <- convrat(radiitree, radii_pca$x[,1:5], radiiflightlesslist)
radiiflightlessconv
radiiflightconvsig <- convratsig(radiitree, radii_pca$x[,1:5], radiiflightlesslist, 10)
radiiflightconvsig
## Convergence test with PC axes
radiiconv <- conv.map(radiidivelist, scores = radii_pca$x, pcs = radii_pca$rotation, mshape = radiimean, focal = "Somateria_mollissima" )
radiiconvtest <- convnum(duck_tree_radii, radii_pca$x[,1:5], radiidivelist)
ref <- mshape(radius.gpa$coords)
ref_obj <- read.ply("Anas_platyrhynchos_MCZ347156_radius.ply", ShowSpecimen = F)
ref_lnd <- readland.fcsv("Anas_platyrhynchos_MCZ347156_radius.fcsv")
warped_ref <- warpRefMesh(ref_obj, ref_lnd, ref, color = "ivory", centered = FALSE)
g2 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$min, mesh=warped_ref, method = "surface")
g3 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$max, mesh=warped_ref, method = "surface")
g4 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$min, mesh=warped_ref, method = "surface")
g5 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$max, mesh=warped_ref, method = "surface")
mesh2ply(warped_ref, "radius_ref")
mesh2ply(g2, "radius_pc1_min")
mesh2ply(g3, "radius_pc1_max")
mesh2ply(g4, "radius_pc2_min")
mesh2ply(g5, "radius_pc2_max")
logfile <- parser("gpa/Ulna/analysis.log", forceLPS = T)
ulna.gpa <- gpagen(logfile$LM, print.progress = F)
ulnashape <- ulna.gpa$coords
dimnames(ulnashape)[[3]] <- sub("^([^_]+_[^_]+).*", "\\1", dimnames(ulnashape)[[3]])
ulnasize <- log10(ulna.gpa$Csize)
names(ulnasize) <- dimnames(ulnashape)[[3]]
duck_tree_ulna <- keep.tip(duck_tree_orig, duck_data$Scientific_Name[duck_data$Ulna %in% "X"])
dimnames(ulna.gpa$coords)[[3]] <- unlist(lapply(str_split(dimnames(ulna.gpa$coords)[[3]], "_"), FUN = function(x){paste(x[1], x[2], sep="_")}))
ulna_pca <- gm.prcomp(ulna.gpa$coords, phy = duck_tree_ulna)
# pc1 (28.35%), pc2 (19.04%), pc3 (14.70%), pc4 (7.03%), pc5 (5.61%)
asp_ratio <- 1.618
duck_pca <- data.frame(species=names(ulna_pca$x[,1]), PC1=ulna_pca$x[,1], PC2=ulna_pca$x[,2], PC3=ulna_pca$x[,3], PC4=ulna_pca$x[,4], PC5=ulna_pca$x[,5])
duck_pca <- merge(duck_pca, duck_data[,c("Scientific_Name", "Images", "Ulna")], by.x = "species", by.y = "Scientific_Name", all.x = T, all.y = F)
g1 <- ggplot(duck_pca, aes(PC1, PC2)) +
geom_image(aes(image=Images), size=0.075, by = "width", asp = asp_ratio)+
theme_classic()+
theme(aspect.ratio = 1/asp_ratio)
g1
Then we check for convergence
ulnashape <- ulnashape[,,duck_tree_ulna$tip.label]
ulnasize <- ulnasize[duck_tree_ulna$tip.label]
ulnabm <- duckbm[duck_tree_ulna$tip.label]
ulnaflight <- flight[duck_tree_ulna$tip.label]
ulnadiving <- diving[duck_tree_ulna$tip.label]
ulnaallom1 <- procD.pgls(ulnashape ~ ulnabm, phy = duck_tree_ulna, SS.type = "II", iter = 999)
summary(ulnaallom1)
ulnaallom2 <- procD.pgls(ulnashape ~ ulnasize, phy = duck_tree_ulna,SS.type = "II", iter = 999)
summary(ulnaallom2)
ulnaallom3 <- procD.pgls(ulnashape ~ ulnabm + ulnasize, phy = duck_tree_ulna, SS.type = "II", iter = 999)
summary(ulnaallom3)
ulna.mod <- procD.pgls(ulnashape ~ ulnabm + ulnasize + ulnadiving, phy = duck_tree_ulna, SS.type = "II", iter = 999)
summary(ulna.mod)
ulna.mod <- procD.pgls(ulnashape ~ ulnabm + ulnasize + ulnadiving + ulnaflight, phy = duck_tree_ulna, SS.type = "II", iter = 999)
summary(ulna.mod)
#convergence
### find convergence test for 3D data
ulnadivelist <- names(ulnadiving[ulnadiving == "Diving"])
ulnadivconv <- convrat(duck_tree_ulna, ulna_pca$x[,1:5], ulnadivelist)
ulnadivconvsig <- convratsig(duck_tree_ulna, ulna_pca$x[,1:5], ulnadivelist, 10)
ulnadivconvsig
## convergence in flightless ducks
ulnaflightlesslist <- names(ulnaflight[ulnaflight == "0"])
ulnaflightlessconv <- convrat(ulnatree, ulna_pca$x[,1:5], ulnaflightlesslist)
ulnaflightlessconv
ulnaflightconvsig <- convratsig(ulnatree, ulna_pca$x[,1:5], ulnaflightlesslist, 10)
ulnaflightconvsig
## Convergence test with PC axes
ulnaconv <- conv.map(ulnadivelist, scores = ulna_pca$x, pcs = ulna_pca$rotation, mshape = ulnamean, focal = "Somateria_mollissima" )
ulnaconvtest <- convnum(duck_tree_ulna, ulna_pca$x[,1:5], ulnadivelist)
ref <- mshape(ulna.gpa$coords)
ref_obj <- read.ply("Anas_platyrhynchos_MCZ347156_ulna.ply", ShowSpecimen = F)
ref_lnd <- readland.fcsv("Anas_platyrhynchos_MCZ347156_ulna.fcsv")
warped_ref <- warpRefMesh(ref_obj, ref_lnd, ref, color = "ivory", centered = FALSE)
g2 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$min, mesh=warped_ref, method = "surface")
g3 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$max, mesh=warped_ref, method = "surface")
g4 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$min, mesh=warped_ref, method = "surface")
g5 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$max, mesh=warped_ref, method = "surface")
mesh2ply(warped_ref, "ulna_ref")
mesh2ply(g2, "ulna_pc1_min")
mesh2ply(g3, "ulna_pc1_max")
mesh2ply(g4, "ulna_pc2_min")
mesh2ply(g5, "ulna_pc2_max")
logfile <- parser("gpa/Carpometacarpus/analysis.log", forceLPS = T)
carpometacarpus.gpa <- gpagen(logfile$LM, print.progress = F)
carposhape <- carpometacarpus.gpa$coords
dimnames(carposhape)[[3]] <- sub("^([^_]+_[^_]+).*", "\\1", dimnames(carposhape)[[3]])
carposize <- log10(carpometacarpus.gpa$Csize)
names(carposize) <- dimnames(carposhape)[[3]]
duck_tree_carpo <- keep.tip(duck_tree_orig, duck_data$Scientific_Name[duck_data$Carpometacarpus %in% "X"])
dimnames(carpometacarpus.gpa$coords)[[3]] <- unlist(lapply(str_split(dimnames(carpometacarpus.gpa$coords)[[3]], "_"), FUN = function(x){paste(x[1], x[2], sep="_")}))
carpo_pca <- gm.prcomp(carpometacarpus.gpa$coords, phy = duck_tree_carpo)
# pc1 (16.79%), pc2 (15.00%), pc3 (14.15%), pc4 (8.73%), pc5 (8.11%)
asp_ratio <- 1.618
duck_pca <- data.frame(species=names(carpo_pca$x[,1]), PC1=carpo_pca$x[,1], PC2=carpo_pca$x[,2], PC3=carpo_pca$x[,3], PC4=carpo_pca$x[,4], PC5=carpo_pca$x[,5])
duck_pca <- merge(duck_pca, duck_data[,c("Scientific_Name", "Images", "Carpometacarpus")], by.x = "species", by.y = "Scientific_Name", all.x = T, all.y = F)
g1 <- ggplot(duck_pca, aes(PC1, PC2)) +
geom_image(aes(image=Images), size=0.075, by = "width", asp = asp_ratio)+
theme_classic()+
theme(aspect.ratio = 1/asp_ratio)
g1
Then we check for convergence
carposhape <- carposhape[,,duck_tree_carpo$tip.label]
carposize <- carposize[duck_tree_carpo$tip.label]
carpobm <- duckbm[duck_tree_carpo$tip.label]
carpoflight <- flight[duck_tree_carpo$tip.label]
carpodiving <- diving[duck_tree_carpo$tip.label]
carpoallom1 <- procD.pgls(carposhape ~ carpobm, phy = duck_tree_carpo, SS.type = "II", iter = 999)
summary(carpoallom1)
carpoallom2 <- procD.pgls(carposhape ~ carposize, phy = duck_tree_carpo,SS.type = "II", iter = 999)
summary(carpoallom2)
carpoallom3 <- procD.pgls(carposhape ~ carpobm + carposize, phy = duck_tree_carpo, SS.type = "II", iter = 999)
summary(carpoallom3)
carpo.mod <- procD.pgls(carposhape ~ carpobm + carposize + carpodiving, phy = duck_tree_carpo, SS.type = "II", iter = 999)
summary(carpo.mod)
carpo.mod <- procD.pgls(carposhape ~ carpobm + carposize + carpodiving + carpoflight, phy = duck_tree_carpo, SS.type = "II", iter = 999)
summary(carpo.mod)
#convergence
### find convergence test for 3D data
carpodivelist <- names(carpodiving[carpodiving == "Diving"])
carpodivconv <- convrat(duck_tree_carpo, carpo_pca$x[,1:5], carpodivelist)
carpodivconvsig <- convratsig(duck_tree_carpo, carpo_pca$x[,1:5], carpodivelist, 10)
carpodivconvsig
## convergence in flightless ducks
carpoflightlesslist <- names(carpoflight[carpoflight == "0"])
carpoflightlessconv <- convrat(carpotree, carpo_pca$x[,1:5], carpoflightlesslist)
carpoflightlessconv
carpoflightconvsig <- convratsig(carpotree, carpo_pca$x[,1:5], carpoflightlesslist, 10)
carpoflightconvsig
## Convergence test with PC axes
carpoconv <- conv.map(carpodivelist, scores = carpo_pca$x, pcs = carpo_pca$rotation, mshape = carpomean, focal = "Somateria_mollissima" )
carpoconvtest <- convnum(duck_tree_carpo, carpo_pca$x[,1:5], carpodivelist)
ref <- mshape(carpometacarpus.gpa$coords)
ref_obj <- read.ply("Anas_platyrhynchos_MCZ347156_carpometacarpus.ply", ShowSpecimen = F)
ref_lnd <- readland.fcsv("Anas_platyrhynchos_MCZ347156_carpometacarpus.fcsv")
warped_ref <- warpRefMesh(ref_obj, ref_lnd, ref, color = "ivory", centered = FALSE)
g2 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$min, mesh=warped_ref, method = "surface")
g3 <- plotRefToTarget(ref, pca$shapes$shapes.comp1$max, mesh=warped_ref, method = "surface")
g4 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$min, mesh=warped_ref, method = "surface")
g5 <- plotRefToTarget(ref, pca$shapes$shapes.comp2$max, mesh=warped_ref, method = "surface")
mesh2ply(warped_ref, "carpometacarpus_ref")
mesh2ply(g2, "carpometacarpus_pc1_min")
mesh2ply(g3, "carpometacarpus_pc1_max")
mesh2ply(g4, "carpometacarpus_pc2_min")
mesh2ply(g5, "carpometacarpus_pc2_max")
duck_pca_genome <- duck_pca[which(duck_pca$species %in% duck_data$Scientific_Name[!is.na(duck_data$Genomes)]),]
duck_tree_genome <- keep.tip(duck_tree, duck_pca_genome$species)
duck_pca_genome$species <- factor(duck_pca_genome$species, levels = duck_tree_genome$tip.label)
duck_pca_genome <- duck_pca_genome[order(duck_pca_genome$species),]
p <- ggtree(duck_tree_genome) +
xlim(NA,0.2)+
geom_tiplab(size=3)+
geom_facet(panel = "Femur_PC1", geom = geom_col, data = duck_pca_genome,
mapping = aes(x = PC1), orientation='y', width=0.6)+
geom_tiplab(aes(image = c(duck_pca_genome$Images, rep("NA", 24))), geom="image",
offset=0.1, align = T)
facet_widths(p, c(0.75, 0.25))
duck_pca_genome <- duck_pca[which(duck_pca$species %in% duck_data$Scientific_Name[!is.na(duck_data$Genomes)]),]
duck_tree_genome <- keep.tip(duck_tree, duck_pca_genome$species)
duck_pca_genome$species <- factor(duck_pca_genome$species, levels = duck_tree_genome$tip.label)
duck_pca_genome <- duck_pca_genome[order(duck_pca_genome$species),]
p <- ggtree(duck_tree_genome) +
xlim(NA,0.2)+
geom_tiplab(size=3)+
geom_facet(panel = "tarsometatarsus_PC1", geom = geom_col, data = duck_pca_genome,
mapping = aes(x = PC1), orientation='y', width=0.6)+
geom_tiplab(aes(image = c(duck_pca_genome$Images, rep("NA", 22))), geom="image",
offset=0.1, align = T)
facet_widths(p, c(0.75, 0.25))
duck_pca_genome <- duck_pca[which(duck_pca$species %in% duck_data$Scientific_Name[!is.na(duck_data$Genomes)]),]
duck_tree_genome <- keep.tip(duck_tree, duck_pca_genome$species)
duck_pca_genome$species <- factor(duck_pca_genome$species, levels = duck_tree_genome$tip.label)
duck_pca_genome <- duck_pca_genome[order(duck_pca_genome$species),]
p <- ggtree(duck_tree_genome) +
xlim(NA,0.2)+
geom_tiplab(size=3)+
geom_facet(panel = "humerus_PC1", geom = geom_col, data = duck_pca_genome,
mapping = aes(x = PC1), orientation='y', width=0.6)+
geom_tiplab(aes(image = c(duck_pca_genome$Images, rep("NA", 26))), geom="image",
offset=0.1, align = T)
facet_widths(p, c(0.75, 0.25))
duck_pca_genome <- duck_pca[which(duck_pca$species %in% duck_data$Scientific_Name[!is.na(duck_data$Genomes)]),]
duck_tree_genome <- keep.tip(duck_tree, duck_pca_genome$species)
duck_pca_genome$species <- factor(duck_pca_genome$species, levels = duck_tree_genome$tip.label)
duck_pca_genome <- duck_pca_genome[order(duck_pca_genome$species),]
p <- ggtree(duck_tree_genome) +
xlim(NA,0.2)+
geom_tiplab(size=3)+
geom_facet(panel = "carpometacarpus_PC1", geom = geom_col, data = duck_pca_genome,
mapping = aes(x = PC1), orientation='y', width=0.6)+
geom_tiplab(aes(image = c(duck_pca_genome$Images, rep("NA", 19))), geom="image",
offset=0.1, align = T)
facet_widths(p, c(0.75, 0.25))
We aligned 27 duck genomes (GenBank numbers in table) and also included the chicken genomes using progressive cactus. The tree used for the alignment is shown below.
(((((((((Aix_galericulata:0.0051473029,Aix_sponsa:0.0053483288):0.0017143373,(Cairina_moschata:0.0016771265,Asarcornis_scutulata:0.0016771265):0.0050313795):0.0030667213,((((Lophonetta_specularioides:0.0100951666,Tachyeres_brachypterus:0.0055556181):0.0028194957,((Anas_acuta:0.0042863335,(Anas_platyrhynchos:0.00124933445,Anas_zonorhyncha:0.00124933445):0.00374800335):0.001201751,(Mareca_sibilatrix:0.0037871541,Mareca_strepera:0.0037867301):0.0014935713):0.0011642544):0.0004165566,Spatula_discors:0.007856085):0.0023604916,Aythya_fuligula:0.009531404):0.0012462578):0.0009209619,(Melanitta_fusca:0.0064818964,(Clangula_hyemalis:0.0070627445,Somateria_mollissima:0.0073593856):0.0003851771):0.0014142496):0.0173506804,((((Anser_fabalis:0.0020284789,Anser_cygnoides:0.001826199):0.0008868183,Anser_indicus:0.0025060375):0.0036566335,Branta_canadensis:0.006571712):0.0029378261,Cygnus_olor:0.0091439003):0.0085572595):0.000654519,(((Heteronetta_atricapilla:0.0213298248,Stictonetta_naevosa:0.0132137813):0.0004721905,Oxyura_jamaicensis:0.0155460859):0.0065766967,Nettapus_auritus:0.0249469325):0.0034281317):0.0328791421,Anseranas_semipalmata:0.0308188616):0.01,Anhima_cornuta:0.0500106949):0.01,Gallus_gallus:0.0308188616);
To run cactus:
#!/bin/bash
#SBATCH -c 1
#SBATCH -t 99-00:00
#SBATCH -p holy-smokes
#SBATCH --nodelist=holy7c0908
#SBATCH --mem=1000
#SBATCH -o ./logs/cac_%j.out
#SBATCH -e ./logs/cac_%j.err
cd /n/holyscratch01/informatics/sshakya/ducks/
source activate PhyloAcc
singularity exec --cleanenv cactus_v2.7.1-gpu.sif cactus-prepare duck_aln.txt --outDir snk_output --jobStore snk_temp --gpu
snakemake -p -s ~/GenomeAnnotation/genome_alignment2/cactus-gpu-snakemake/cactus_gpu.smk --configfile duck_aln.yaml --profile ~/GenomeAnnotation/genome_alignment2/cactus-gpu-snakemake/profiles/slurm_profile/
To get neutral rates, we used the chicken annotations. See conserved_rates for steps to get neutral rates.
We used the coordinates from conserved elements produced in Shakya et al. for getting alignments of conserved elements. See elements_fasta for steps to get conserved elements.
We ran PhyloAcc-C model for PC1 of each of the four selected bones. To run PhyloAcc-C, we used the following code:
library(coda)
library(parallel)
suppressMessages(library(sm))
library(argparse)
library(stringi)
library(ape)
ELL_do_mcmc = function(row_i) {
mclapply(1:args$runs, function(i) {
pac3::run_model(tree=tree, alignment=(all_alignments[[row_i]]),
trait_tbl=trait_tbl,
transition_matrix=Q, stationary_distro=PI, n_iter=args$iter,
inner_iter=500,
Phi_prior=c(1.0, 1.0, 1.0, 1.0, 1.0, 1.0),
prior_r2=c(4,0.1),
prior_r3=c(10,0.4))
}, mc.cores=1) # N.B. set to 1 = lapply, so do parallelism at element level
}
ELL_make_mcmclist = function(mcmc_outs, n_burnin=n_burnin, n_thin=1) {
cs <- lapply(mcmc_outs, function(mcmc_out) {
the_trace = with(mcmc_out$mcmc_trace,
data.frame(lv =v_trace[,1],
lb2=v_trace[,2],
lb3=v_trace[,3]))
as.mcmc(the_trace, start=(n_burnin+1), thin=n_thin)
})
as.mcmc.list(cs)
}
do_ith_element = function(i) {
print(paste("Working on element ",i," of ",length(all_alignments)," of batch ",ceiling(start_index/args$batch_size) , sep=""))
the_mcmc_outs = ELL_do_mcmc(i)
the_trace = do.call(rbind, lapply(1:args$runs, function(i) the_mcmc_outs[[i]]$mcmc_trace$v_trace[-(1:args$burnin),])) # needs the rbind otherwise don't get correct quantiles
the_mcmc_list = ELL_make_mcmclist(the_mcmc_outs)
rhat = gelman.diag(the_mcmc_list)$mpsrf
the_density = sm.density(the_trace[,2:3], model="Normal", eval.grid=F, eval.points=matrix(data=c(0,0), byrow=T, nrow=1, ncol=2), display="none")
the_density2= sm.density(the_trace[,3]-the_trace[,2], model="Normal", eval.grid=F, eval.points=0, display="none")
qlv = as.numeric(quantile(the_trace[,1], prob=c(.1,.5,.9)))
qlb2 = as.numeric(quantile(the_trace[,2], prob=c(.1,.5,.9)))
qlb3 = as.numeric(quantile(the_trace[,3], prob=c(.1,.5,.9)))
qrat = as.numeric(quantile(the_trace[,3]- the_trace[,2], prob=c(.1,.5,.9)))
list( lv.10=qlv [1], lv.50=qlv [2], lv.90=qlv [3],
lb2.10=qlb2[1], lb2.50=qlb2[2], lb2.90=qlb2[3],
lb3.10=qlb3[1], lb3.50=qlb3[2], lb3.90=qlb3[3],
rat.10=qrat[1], rat.50=qrat[2], rat.90=qrat[3],
rhat=as.numeric(rhat),
dens0=as.numeric(the_density$estimate),
densr=as.numeric(the_density2$estimate))
}
do_these_elements = function(indices) {
mclapply(indices, function(i) {
the_res = do_ith_element(i)
the_res$NAME = names(all_alignments[i])
the_res
}, mc.cores=args$cores)
}
# Create Argument Parser
parser <- ArgumentParser(description = "Run PhyloAcc-c")
# Add arguments
parser$add_argument("--mod_file", type="character", help = "Path to mod file with tree and neutral rates")
parser$add_argument("--output", type="character", help = "Output file name")
parser$add_argument("--output_folder", default="./", type="character", help = "Output folder name (default = ./)")
parser$add_argument("--fasta", type="character", help = "Fasta folder")
parser$add_argument("--fasta_list", type="character", help = "Optional list to only include from fasta")
parser$add_argument("--traits", type="character", help = "Tab-delimited file with species and trait")
parser$add_argument("--batch_size", type="integer", default=100, help = "How many elements to run and write at one time")
parser$add_argument("--runs", type="integer", default=3, help = "Number of runs per element (default=3)")
parser$add_argument("--cores", type="integer", default=1, help = "How many cores to run in parallel")
parser$add_argument("--iter", type="integer", default=10000, help = "Number of iterations per element (default=10000)")
parser$add_argument("--burnin", type="integer", default=1000, help = "Number of iterations of burnin to discard (default=1000)")
parser$add_argument("--max_missing", type="double", default=0.5, help = "Fraction of taxa need to be present in alignment (default=0.5)")
# Parse arguments
args <- parser$parse_args()
print(args)
# Parse mod file
lines <- readLines(args$mod_file)
for (line_index in seq_along(lines)) {
# Split the line by ":"
parts <- stri_split_fixed(lines[line_index], ":", n=2)[[1]]
# Extract variable name and IDs
variable <- trimws(parts[1]) # Trim whitespace
if (variable == "BACKGROUND") {
PI <- as.numeric(unlist(strsplit(trimws(parts[2]), "\\s+")))
}
if (variable == "RATE_MAT"){
mat_vals <- strsplit(lines[(line_index+1):(line_index+4)], "\\s+")
Q <- do.call(rbind, mat_vals)
Q <- Q[,-1]
Q <- matrix(as.numeric(Q), nrow=4, byrow=T)
line_index <- line_index + 4
}
if (variable == "TREE"){
tree = read.tree(text = trimws(parts[2]))
tree$node.label <- paste("Anc", 0:Nnode(tree), sep="")
}
}
# Get trait data
trait_tbl <- read.table(args$traits)
colnames(trait_tbl) <- c("NAME", "Y")
tree <- keep.tip(tree, trait_tbl$NAME)
trait_tbl$NAME <- factor(trait_tbl$NAME, levels = tree$tip.label)
trait_tbl <- trait_tbl[order(trait_tbl$NAME),]
row.names(trait_tbl) <- 1:nrow(trait_tbl)
alignment_loc <- args$fasta
fasta_files <- list.files(alignment_loc, full.names = T, include.dirs = F)
fasta_basenames <- tools::file_path_sans_ext(basename(fasta_files))
if (!is.null(args$fasta_list)){
keep_fasta <- read.table(args$fasta_list)
fasta_files <- fasta_files[which(fasta_basenames %in% keep_fasta$V1)]
fasta_basenames <- fasta_basenames[which(fasta_basenames %in% keep_fasta$V1)]
}
#some basic housekeeping
start_run <- T
if (!file.exists(args$output_folder)) {
# If it doesn't exist, create the output folder
dir.create(args$output_folder)
}
# Loop in batches of batch size
for (start_index in seq(1, length(fasta_files), by = args$batch_size)){
all_alignments <- list()
for (each_file in start_index:(start_index + args$batch_size - 1)){
element <- fasta_basenames[each_file]
alignment <- read.dna(fasta_files[each_file], format = "fasta", as.matrix = T, as.character = T)
if ((nrow(alignment) > ((length(tree$tip.label))*args$max_missing))) {
alignment <- alignment[rownames(alignment) %in% trait_tbl$NAME,]
alignment[alignment=="*"] <- "-"
alignment[alignment=="n"] <- "-"
all_same <- all(apply(alignment, 2, function(x) length(unique(x))) == 1)
missing_taxa <- setdiff(tree$tip.label, rownames(alignment))
if (length(missing_taxa > 0)){
for (miss in missing_taxa){
missing_row <- matrix(rep("-", ncol(alignment)), nrow=1)
rownames(missing_row) <- miss
alignment <- rbind(alignment, missing_row)
}
}
if (!all_same){
all_alignments <- append(all_alignments, setNames(list(alignment), element))
}
}
}
if(length(all_alignments) > 0){
system.time(yyy <- do_these_elements(1:length(all_alignments)))
tbl_to_write = do.call(rbind, yyy)
out_fn = paste(args$output_folder, "/", args$output, ".tsv", sep="")
if (file.exists(out_fn) & start_run){
write.table(tbl_to_write, out_fn, sep="\t", row.names=F, quote=F, col.names=T)
start_run <- F
}
write.table(tbl_to_write, out_fn, sep="\t", row.names=F, quote=F, col.names=F, append=T)
}
}
This script can then be run as such:
scaffold="NC_052572.1"
Rscript run_phyloaccc.r --mod_file ducks_4d_Z_non-conserved.mod --output ${scaffold} --output_folder phylo_out_carpometacarpus --trait duck_carpometacarpus_pc1.txt --fasta fasta/fasta_Z/${scaffold}/ --fasta_list bed_ranges/${scaffold}.txt --batch_size 200 --cores 40 --iter 10000 --burnin 1000