#### Importing Data ####__________________________________________________________________________ setwd("~/Desktop/Masters/2. Morphometrics/Morphometrics Data Collection/GMM Analysis/Datasets:Analyses/") rearranged_gecko<-read.csv("SymmetricShape2020.csv", h=T) # Flip Z-Axis to Mirror Lefts on Rights rawdata <- arrayspecs(rearranged_gecko[,c(5:ncol(rearranged_gecko))], p=55, k=3) dim(rawdata) # [1] 55 3 30, p k n rawdata[,3,which(rearranged_gecko$Side=="Left")] <- rawdata[,3,which(rearranged_gecko$Side=="Left")] * rep(-1,dim(rawdata)[1]) gecko_matrix<-rawdata # Defining Curves - Geomorph define.sliders(gecko_matrix, 40, write.file=T) geckosliders <- rbind(define.sliders(16:25), define.sliders(26:35), define.sliders(36:45), define.sliders(46:55)) #### Assymetry ####__________________________________________________________________________ # Assessing Asymmetry in Left-Right Maxillae Shape (+ Measurement Error) ind <- rearranged_gecko$Specimen side <- rearranged_gecko$Side rep <- rearranged_gecko$Replicate max.symmetry<-bilat.symmetry(fixed_gecko.gpa$coords, ind = ind, side = side, replicate = rep, object.sym = FALSE, iter = 9999) max.symmetry$symm.shape max.symmetry$size.anova #### PC Analysis ####__________________________________________________________________________ # Principal Component Analysis (PCA Plot) fixed_gecko.gpa <- gpagen(rawdata, curves=geckosliders) plot(fixed_gecko.gpa) gecko.PCA<-plotTangentSpace(fixed_gecko.gpa$coords, axis1 = 1, axis2 = 2, label=TRUE, groups = palette()[rearranged_gecko$Species]) # Morpho #### Canonical Variate Analysis ####__________________________________________________________________________ cva.1<-CVA(gecko.PCA$pc.scores[,1:19], groups = rearranged_gecko$Species, rounds = 10000) plot(cva.1$CVscores, col=cva.1$groups, pch=as.numeric(cva.1$groups), typ="n", asp=1,xlab=paste("1st Canonical Axis", paste(round(cva.1$Var[1,2],1),"%")), ylab=paste("2nd Canonical Axis", paste(round(cva.1$Var[2,2],1),"%"))) text(cva.1$CVscores, as.character(cva.1$groups),col=as.numeric(cva.1$groups), cex=.7) # Mahalanobis distance probabilities cva.1$Dist$probsMaha # Visualize a shape change from score -5 to 5 for CV1/CV2 proc<-procSym(fixed_gecko.gpa$coords) cvvis5 <- 5*cvall$CVvis[,1]+cvall$Grandm cvvisNeg5 <- -5*cvall$CVvis[,1]+cvall$Grandm cvvis5 <- showPC(cvvis5,proc$PCs,proc$mshape) cvvisNeg5 <- showPC(cvvisNeg5,proc$PCs,proc$mshape) deformGrid3d(cvvis5,cvvisNeg5,ngrid = 0) CVA1p<-cvvis5 CVA1n<-cvvisNeg5 cvvis5_2 <- 5*cvall$CVvis[,2]+cvall$Grandm cvvisNeg5_2 <- -5*cvall$CVvis[,2]+cvall$Grandm cvvis5_2 <- showPC(cvvis5_2,proc$PCs,proc$mshape) cvvisNeg5_2 <- showPC(cvvisNeg5_2,proc$PCs,proc$mshape) deformGrid3d(cvvis5_2,cvvisNeg5_2,ngrid = 0) CVA2p<-cvvis5_2 CVA2n<-cvvisNeg5_2 # Classifying Unknown Specimens in CVA write.csv(gecko.PCA$pc.scores, "Gecko_PC_Scores.csv") ModernPC<-read.csv("Modern_PC_Scores.csv", h=T) # Separate known and unknown PC scores SubfossilPC<-read.csv("Subfossil_PC_Scores.csv", h=T) PCID<-read.csv("Taxonomic_ID.csv") CVAProb<-typprobClass(SubfossilPC, ModernPC, groups = PCID$Species,small = T, method = "wilson", cova = T, outlier = 0.2, cv =T) CVAProb$probsCV CVAProb$groupaffin CVAProb$probs #### Linear Discriminant Analysis (LDA) ####________________________________________________________________________ # Run LDA Analysis gecko.lda<-lda(ModernPC, grouping = PCID$Species,CV=F) #Performs LDA modern.pred<-predict(gecko.lda, ModernPC) #Get Modern Probabilities sub.pred<-predict(gecko.lda, SubfossilPC) #Performs Prediction # See LDA Results subfossil.posteriors<-sub.pred$posterior subfossil.class<-sub.pred$class subfossil.scores<-sub.pred$x # Visualise LDA write.csv(modern.pred$x, "Modern_LD_Score.csv") write.csv(sub.pred$x, "Subfossil_LD_Score.csv") LDScores<-read.csv("LD_Scores.csv", h=T) plot(LDScores$LD2 ~ LDScores$LD1, col=as.numeric(LDScores$Species)) text(LDScores$LD2 ~ LDScores$LD1, labels=LDScores$Specimen, data=LDScores, cex=0.3, font=0.5) # 95% Confidence Ellipse dataEllipse(LDScores$LD1, LDScores$LD2, groups = LDScores$Species, levels=c(0.95)) # Calculating Mean Shapes for Genera Dactylocnemis <- mshape(fixed_gecko.gpa$coords[,,1:9]) Hoplodactylus <- mshape(fixed_gecko.gpa$coords[,,10:16]) Mokopirirakau <- mshape(fixed_gecko.gpa$coords[,,17:21]) Naultinus <- mshape(fixed_gecko.gpa$coords[,,22:30]) Woodworthia <- mshape(fixed_gecko.gpa$coords[,,43:55]) #### Procrustes ANOVA Analyses ####__________________________________________________________ # Multivariate Regression for Allometry (test for slope differences between groups) MVAllom.1<-procD.lm(gecko.PCA$pc.scores[,1:19] ~ rearranged_gecko$Csize * rearranged_gecko$Species, data = fixed_gecko.gpa, iter=9999) summary(MVAllom.1) MVAllom.1.pair<-pairwise(MVAllom.1, groups = rearranged_gecko$Species) summary(MVAllom.1.pair, confidence = 0.95) # ANOVA + Tukey-Test for Size Differences bartlett.test(Csize ~ Species, data = rearranged_gecko) csizeANOVA<-aov(Csize ~ Species, data = rearranged_gecko) summary(csizeANOVA) TukeyHSD(csizeANOVA) # Barplot_CSize_Means/SE means <- tapply(rearranged_gecko$Csize, rearranged_gecko$Species, FUN = mean, na.rm = T) sds <- tapply(rearranged_gecko$Csize, rearranged_gecko$Species, FUN = sd, na.rm = T) ns <- tapply(rearranged_gecko$Csize, rearranged_gecko$Species, FUN = length) ses<-sds/sqrt(ns) mp<-barplot(means, ylim=c(0,2100)) box(bty = "l") segments(mp, means - 2*ses, mp, means + 2*ses, lwd=1.5) segments(mp - 0.04, means - 2*ses, mp + 0.04, means - 2*ses, lwd=1.5) segments(mp - 0.04, means + 2*ses, mp + 0.04, means + 2*ses, lwd=1.5) stripchart(Csize ~ Species, data = rearranged_gecko, vertical = T, add = T, pch = 21, method = "jitter") #### Assessing Phylogenetic Signal ####______________________________________________________ # Creating a Tree File gecko.tree<-"geckos(((H._duvaucelii_S:0.37, H._duvaucelii:0.26):1.27, ((W._maculata:1.08, W._Otago_large:1.11):0.25, W._chrysosireticus:1.25):0.22):0.37, (((M._granulatus:0.65, M._granulatus_southern_NI:0.66):0.14, ((D._pacificus:0.68, D._mokohinaus:0.67):0.06, D._three_kings:0.62):0.29):0.13, ((N._elegans:0.19, N._punctatus:0.18):0.09, N._stellatus:0.27):0.86):0.25);" cat(gecko.tree, file = "gecko.tree") tree.gecko <- read.tree("gecko.tree") plot(tree.gecko) # Creating Species Coordinate Means new.coords<-coords.subset(fixed_gecko.gpa$coords, group = rearranged_gecko$Species) species <- lapply(new.coords, mshape) species<-array(unlist(species), c(55, 3, length(species))) dimnames(species)[[3]] <- levels(rearranged_gecko$Species) # Testing Significance PS.shape<-physignal(species, tree.gecko, iter=999) summary(PS.shape) plotGMPhyloMorphoSpace(tree.gecko, species) #### Creating Warps of PC max ####________________________________________________________________________________ ref <- mshape(fixed_gecko.gpa$coords) mesh <- read.ply("S.33703.3_New.ply") mesh$material$color <- "moccasin" ; open3d(); shade3d(mesh) mesh.coords <- read.morphologika("S.33703.3.txt") plotspec(mesh,mesh.coords[,,1]/1000, centered = F) refmesh <- warpRefMesh(mesh, mesh.coords[,,1]/1000, fixed_gecko.gpa$coords[,,42], centered=FALSE) PCs <- c("mesh") attach(gecko.PCA$pc.shapes) # so we can call each PC shape from this list in the environment for(i in PCs){ tmp <- plotRefToTarget(ref, get(i), method="surface", mesh = refmesh, mag=1) assign(paste("m",i,sep=""), tmp) writePLY(paste("~/Desktop/",i,".ply",sep=""),withColors=T) options(warn = 0) } FOV = 0 # sets parallel projection, rather than orthogonal open3d(); view3d(fov=0);shade3d(refmesh) # open a mesh on rgl # set by hand in rgl window, adjust specimen into dorsal positon then: usrMat.dorsal <- par3d()$userMatrix # save position matrix write.csv(usrMat.dorsal, "usrMat.dorsal.csv",row.names=F) # write to WD for later usrMat.lateral <- par3d()$userMatrix # again, adjust specimen into lateral positon then save write.csv(usrMat.lateral, "usrMat.lateral.csv",row.names=F) usrMat.posterior <- par3d()$userMatrix write.csv(usrMat.posterior, "usrMat.posterior.csv",row.names=F) usrMat.dorsal <- as.matrix(read.csv("usrMat.dorsal.csv", header = T)) usrMat.lateral <- as.matrix(read.csv("usrMat.lateral.csv", header = T)) usrMat.posterior <- as.matrix(read.csv("usrMat.posterior.csv", header = T)) open3d(FOV=0, userMatrix = usrMat.dorsal) # for a dorsal view shade3d(mPC1min) # to see PC1min shape in dorsal view. open3d(FOV=0, userMatrix = usrMat.lateral) # for a lateral view open3d(FOV=0, userMatrix = usrMat.posterior) # for a posterior view views <- c("dorsal", "lateral", "posterior") PCs <- c("ref") for(i in PCs){ for(j in views){ open3d(FOV=0, userMatrix=as.name(paste("usrMat", j, sep=".")), windowRect=c(0,0,600,600)) shade3d(get(paste("m",i,sep="")), alpha=1, lit = T, shininess = 128.0, specular=49) options(warn = 0) rgl.snapshot(paste("~/Desktop/MSc Chapters/3. Morphometrics/GMM Analysis/Datasets:Analyses/3DModels/Figures/","Mesh_",i,"_",j,".png", sep=""), fmt="png", top=TRUE) rgl.close() }}