AnalysisFunctions/process_outputdata.R

# This script was written to analyse the data that is returned from the AvInertia package
## Load up necessary packages
library(phytools)
library(ape)
library(geiger)
library(MCMCglmm)
library(tidyverse)
library(effectsize) # needed for eta_squared calculation
library(pracma)
library(ggplot2)
library(dplyr)
library(reshape2)
source("/Users/christinaharvey/Documents/AvInertia/AnalysisFunctions/calc_np_loc_functions.R")
### ----------------------------------------------------------
### --------------------- Read in data -----------------------
### ----------------------------------------------------------

# CAUTION: if origin is not specified for a variable then it is assumed to be an absolute length

# CAUTION: All incoming measurements must be in SI units; adjust as required
# UPDATE REQUIRED: Should probably move final run files into the bird moment folder
path_data_folder = "/Users/christinaharvey/Dropbox (University of Michigan)/Bird Mass Distribution/outputdata/"

## ------------- Read in the wing shape data --------------
filename_wing  = list.files(path = path_data_folder, pattern = paste("allspecimen_winginfo"))
dat_wing       = read.csv(file = paste(path_data_folder,filename_wing,sep= ""))
dat_wing       = dat_wing[,-c(1)]
# ---- Calculate the base aerodynamic properties of the wings ----
# don't want the y direction included - just want the distance from leading to trailing edge in x-z plane
# using max chord because we know for a gull that the AC is between 19%-43% of the mean chord (~max wing root chord) so this seems like a fair approach
dat_wing$c_root        = sqrt((dat_wing$pt12_X - dat_wing$pt11_X)^2+(dat_wing$pt12_Z - dat_wing$pt11_Z)^2)

dat_wing$c_stan_mean_orgVRP <- 0

# Calculate the standard mean chord which will be used to estimate the aerodynamic centre of the wing-body
for (k in 1:nrow(dat_wing)){
  peri_pts = rbind(c(dat_wing$pt12_X[k],dat_wing$pt12_Y[k],dat_wing$pt12_Z[k]),
                   c(dat_wing$pt6_X[k],dat_wing$pt6_Y[k],dat_wing$pt6_Z[k]),
                   c(dat_wing$pt7_X[k],dat_wing$pt7_Y[k],dat_wing$pt7_Z[k]),
                   c(dat_wing$pt8_X[k],dat_wing$pt8_Y[k],dat_wing$pt8_Z[k]),
                   c(dat_wing$pt9_X[k],dat_wing$pt9_Y[k],dat_wing$pt9_Z[k]),
                   c(dat_wing$pt10_X[k],dat_wing$pt10_Y[k],dat_wing$pt10_Z[k]),
                   c(dat_wing$pt11_X[k],dat_wing$pt11_Y[k],dat_wing$pt11_Z[k]))

  if (dat_wing$pt11_Y[k] > dat_wing$pt12_Y[k]){
    peri_pts = rbind(peri_pts,c(dat_wing$pt11_X[k],dat_wing$pt12_Y[k],dat_wing$pt12_Z[k]))
    # likely will have a portion of the wing area proximal to the last secondary - this estimates the surface area of the tertiaries
    A8 = abs(0.5*Norm(cross(as.vector(t(c(dat_wing$pt11_X[k],dat_wing$pt12_Y[k],dat_wing$pt12_Z[k])-dat_wing[k,c("pt2_X","pt2_Y","pt2_Z")])),
                            as.vector(t(c(dat_wing$pt11_X[k],dat_wing$pt12_Y[k],dat_wing$pt12_Z[k])-dat_wing[k,c("pt11_X","pt11_Y","pt11_Z")]))), p = 2))
    dat_wing$S[k] = dat_wing$S[k] + A8
  }
  dat_wing$c_stan_mean_orgVRP[k] <- find_c4_x(peri_pts,"standard mean") # CAUTION THIS NUMBER IS WITH THE ORIGIN AT THE VRP because of peri_pts
}

dat_wing$c_stan_mean_orgShoulder <- dat_wing$c_stan_mean_orgVRP - dat_wing$pt1_X
# Caution S and S_proj are a single wing area only!

# span is calculated as the furthest distance of the humeral head to either P10, P7 or the point on the digit leading edge.
# The x component is neglected. Measured from the body center line
dat_wing$span         = apply(cbind(2*sqrt(dat_wing$pt8_Y^2+dat_wing$pt8_Z^2),
                                    2*sqrt(dat_wing$pt9_Y^2+dat_wing$pt9_Z^2),
                                    2*sqrt(dat_wing$pt7_Y^2+dat_wing$pt7_Z^2)), 1, max)
dat_wing$AR           = (dat_wing$span^2)/(2*dat_wing$S)
dat_wing$c_mean       = (2*dat_wing$S)/dat_wing$span
dat_wing$AR_proj      = (dat_wing$span^2)/(2*dat_wing$S_proj)
dat_wing$arm_span     = sqrt((dat_wing$pt1_X-dat_wing$pt3_X)^2+(dat_wing$pt1_Y-dat_wing$pt3_Y)^2+(dat_wing$pt1_Z-dat_wing$pt3_Z)^2)
# need this to be distance from wrist joint to wing tip, i.e. not the most exterior position so don't allow pt7 - also I want the full distance
dat_wing$hand_span    = apply(cbind(sqrt((dat_wing$pt8_X-dat_wing$pt3_X)^2+(dat_wing$pt8_Y-dat_wing$pt3_Y)^2+(dat_wing$pt8_Z-dat_wing$pt3_Z)^2),
                                    sqrt((dat_wing$pt9_X-dat_wing$pt3_X)^2+(dat_wing$pt9_Y-dat_wing$pt3_Y)^2+(dat_wing$pt9_Z-dat_wing$pt3_Z)^2)), 1, max)

filename = paste(format(Sys.Date(), "%Y_%m_%d"),"_allwingdata.csv",sep="")
write.csv(dat_wing,filename)

## ------------- Read in the feather data --------------
# CAUTION: This data is not necessary - most recent outputs excel rounded off sig figs if desired should re-run all species in one group to avoid rounding errors
# filename_feat = list.files(path = path_data_folder, pattern = paste("allspecimen_featherinfo"))
# dat_feat      = read.csv(file = paste(path_data_folder,filename_feat,sep= ""))
# dat_feat      = dat_feat[,-c(1,3:7)]

## ------------- Read in the body morphology data --------------
filename_bird = list.files(path = path_data_folder, pattern = paste("allspecimen_birdinfo"))
dat_bird      = read.csv(file = paste(path_data_folder,filename_bird,sep= ""))
names(dat_bird)[names(dat_bird) == "binomial.x"] = "binomial"
dat_bird     = dat_bird[,-c(1)]

# set neck length to zero for those modeled with a retracted neck
for (i in 1:nrow(dat_bird)){
  if(!dat_bird$extend_neck[i]){
    dat_bird$neck_length[i] = 0
  }
}

## ------------- Read in body results from AvInertia --------------
filename_body = list.files(path = path_data_folder, pattern = paste("bodyCGandMOI_correct"))
dat_body      = read.csv(file = paste(path_data_folder,filename_body,sep= ""))
dat_body      = reshape2::dcast(dat_body, species + BirdID + TestID + FrameID ~ component + object, value.var="value")

## ------------- Read in wing configuration results from AvInertia --------------
filename_results = list.files(path = path_data_folder, pattern = paste("results"))
dat_results = read.csv(paste(path_data_folder,filename_results[1],sep=""))
for (i in 2:length(filename_results)){
  dat_results = rbind(dat_results,read.csv(paste(path_data_folder,filename_results[i],sep="")))
}

# clean up environment
remove(filename_wing,filename_bird,filename_body,filename_results)

## ------------- Read in full tree phylogeny --------------
full_tree <- read.nexus("/Users/christinaharvey/documents/AvInertia/AnalysisData/vikROM_passerines_403sp.tre")

### --------------------------------------------------------------
### --------------------- Combine all data -----------------------
### --------------------------------------------------------------

dat_final = merge(dat_results,dat_wing[,c("species","BirdID","TestID","FrameID","BirdID_FrameSpec",
                                          "elbow","manus","S","S_proj","c_root","span","AR","AR_proj","c_stan_mean_orgShoulder",
                                          "c_mean","hand_span","arm_span","pt1_X","pt1_Y","pt1_Z")],
                  by = c("species","BirdID","TestID","FrameID"))
dat_final = merge(dat_final,dat_bird, by = c("species","BirdID"))
dat_final = merge(dat_final,dat_body[,-c(3,4)], by = c("species","BirdID"))

### ------------------------------------------------------------------
### --------------------- Calculate key params -----------------------
### ------------------------------------------------------------------

dat_final$full_length  = (dat_final$torsotail_length+dat_final$head_length+dat_final$neck_length)
dat_final$torso_length = dat_final$torsotail_length - dat_final$tail_length

dat_final$full_CGx_orgBeak             = (dat_final$full_CGx-dat_final$head_length-dat_final$neck_length)
dat_final$full_CGx_specific_orgBeak    = (dat_final$full_CGx-dat_final$head_length-dat_final$neck_length)/dat_final$full_length
dat_final$full_CGz_orgDorsal           = (dat_final$full_CGz+dat_final$z_dist_to_veh_ref_point_cm)
dat_final$full_CGz_specific_orgDorsal  = (dat_final$full_CGz+dat_final$z_dist_to_veh_ref_point_cm)/dat_final$full_length
#dat_final$shoulderx_specific_orgBeak   = (dat_final$pt1_X-dat_final$head_length-dat_final$neck_length)/dat_final$full_length
#dat_final$shoulderz_specific_orgDorsal = (dat_final$pt1_Z+dat_final$z_dist_to_veh_ref_point_cm)/dat_final$full_length

dat_final$full_CGx_specific_orgShoulder = (dat_final$full_CGx-dat_final$pt1_X)/dat_final$full_length
dat_final$full_CGx_orgShoulder          = (dat_final$full_CGx-dat_final$pt1_X)
dat_final$full_CGz_specific_orgShoulder = (dat_final$full_CGz-dat_final$pt1_Z)/dat_final$full_length
dat_final$full_CGz_orgShoulder          = (dat_final$full_CGz-dat_final$pt1_Z)
#dat_final$BeakTipx_orgShoulder          = (dat_final$head_length+dat_final$neck_length+dat_final$pt1_X)/dat_final$full_length
#dat_final$Centrez_orgShoulder           = (dat_final$pt1_Z)/dat_final$full_length
#dat_final$TailTipx_orgShoulder          = (-dat_final$torsotail_length-dat_final$pt1_X)/dat_final$full_length
#dat_final$MaxWidthx_orgShoulder         = (-dat_final$x_loc_of_body_max-dat_final$pt1_X)/dat_final$full_length
#dat_final$Dorsalz_orgShoulder           = -(dat_final$z_dist_to_veh_ref_point_cm+dat_final$pt1_Z)/dat_final$full_length
#dat_final$Ventralz_orgShoulder          = (dat_final$body_height_max-(dat_final$z_dist_to_veh_ref_point_cm+dat_final$pt1_Z))/dat_final$full_length

dat_final$elbow_scaled = dat_final$elbow*0.001
dat_final$manus_scaled = dat_final$manus*0.001

### ---------------------------------------------------------------------------------------
### --------------------------- Compute summed quantities ---------------------------------
### ---------------------------------------------------------------------------------------
# Maximum projected wing area and maximum wing span
test1       <- aggregate(list(S_proj_max = dat_final$wing_S_proj, # CAUTION: Half wing projected area
                             S_max = dat_final$S,    # CAUTION: Half wing area
                             b_max = dat_final$span, # CAUTION: this span includes both y and z components
                             c_root_max = dat_final$c_root),  by=list(species = dat_final$species, BirdID = dat_final$BirdID), max)
test2       <- aggregate(list(c_mean_mean = dat_final$c_mean),  by=list(species = dat_final$species, BirdID = dat_final$BirdID), mean)
test <- merge(test1,test2, by = c("species","BirdID"))
dat_bird   <- merge(dat_bird,test, by = c("species","BirdID"))
dat_final  <- merge(dat_final,test, by = c("species","BirdID"))

# non-dimensionalize the neutral point predictor
dat_final$x_np_proxy_nd <- dat_final$c_stan_mean_orgShoulder/dat_final$c_root_max # this is defined with the VRP axes i.e. will be negative

dat_final$wing_CGy_orgShoulder           = (dat_final$wing_CGy-dat_final$pt1_Y)
dat_final$wing_CGy_specific              = (dat_final$wing_CGy)/(0.5*dat_final$b_max)
dat_final$wing_CGy_specific_orgShoulder  = (dat_final$wing_CGy-dat_final$pt1_Y)/(0.5*dat_final$b_max)
dat_final$wing_CGx_specific_orgBeak      = (dat_final$wing_CGx-dat_final$head_length-dat_final$neck_length)/(0.5*dat_final$b_max)
dat_final$wing_CGx_specific_orgShoulder  = (dat_final$wing_CGx-dat_final$pt1_X)/(0.5*dat_final$b_max)
dat_final$wing_CGz_specific              = dat_final$wing_CGz/(0.5*dat_final$b_max)

dat_final$full_Ixx_specific  = dat_final$full_Ixx/(dat_final$full_m*dat_final$b_max*dat_final$full_length)
dat_final$full_Iyy_specific  = dat_final$full_Iyy/(dat_final$full_m*dat_final$b_max*dat_final$full_length)
dat_final$full_Izz_specific  = dat_final$full_Izz/(dat_final$full_m*dat_final$b_max*dat_final$full_length)
dat_final$full_Ixz_specific  = dat_final$full_Ixz/(dat_final$full_m*dat_final$b_max*dat_final$full_length)

# Shoulder position specific and mass
test     <- aggregate(list(full_m = dat_final$full_m),  by=list(species = dat_final$species, BirdID = dat_final$BirdID), max)
dat_bird <- merge(dat_bird,test, by = c("species","BirdID"))

### ---------------------------------------------------------------------------------------
### ------------- Compute extremes of the CG position due to shoulder motion --------------
### ---------------------------------------------------------------------------------------

angle_shoulder = 90
# the most effect will be felt for the wing that has the most distal CG position (independent from it's x or z position)
dat_final$shoulderCG_dist <- sqrt((dat_final$wing_CGy-dat_final$pt1_Y)^2)
tmp = aggregate(list(max_wingCG = dat_final$shoulderCG_dist),
                       by=list(species = dat_final$species, BirdID = dat_final$BirdID), max)
shoulder_motion = dat_final[which(dat_final$shoulderCG_dist %in% tmp$max_wingCG),c("species","BirdID","elbow","manus","wing_CGx","wing_CGy","wing_CGz","pt1_X","pt1_Y","pt1_Z","b_max",
                                                                             "wing_m","full_m","full_CGx","full_CGy","full_CGz","full_length","head_length","neck_length","binomial")]
shoulder_motion$rest_m   = (shoulder_motion$full_m-2*shoulder_motion$wing_m)
shoulder_motion$rest_CGx = (shoulder_motion$full_m*shoulder_motion$full_CGx - 2*(shoulder_motion$wing_m*shoulder_motion$wing_CGx))/shoulder_motion$rest_m
shoulder_motion$rest_CGz = (shoulder_motion$full_m*shoulder_motion$full_CGz - 2*(shoulder_motion$wing_m*shoulder_motion$wing_CGz))/shoulder_motion$rest_m

# - Rotate the wing forward about the shoulder in the x-y plane - allows a rotation about Pt1
new_wing_CGx = (cosd(angle_shoulder)*(shoulder_motion$wing_CGx-shoulder_motion$pt1_X) + sind(angle_shoulder)*(shoulder_motion$wing_CGy-shoulder_motion$pt1_Y)) + shoulder_motion$pt1_X
#new_wing_CGy = (-sind(angle_shoulder)*(shoulder_motion$wing_CGx-shoulder_motion$pt1_X) + cosd(angle_shoulder)*(shoulder_motion$wing_CGy-shoulder_motion$pt1_Y)) + shoulder_motion$pt1_Y
shoulder_motion$forward_CGx = (shoulder_motion$rest_m*shoulder_motion$rest_CGx + 2*shoulder_motion$wing_m*new_wing_CGx)/shoulder_motion$full_m

# - Rotate the wing backwards about the shoulder in the x-y plane
new_wing_CGx = (cosd(-angle_shoulder)*(shoulder_motion$wing_CGx-shoulder_motion$pt1_X) + sind(-angle_shoulder)*(shoulder_motion$wing_CGy-shoulder_motion$pt1_Y)) + shoulder_motion$pt1_X
#new_wing_CGy = (-sind(-angle_shoulder)*(shoulder_motion$wing_CGx-shoulder_motion$pt1_X) + cosd(-angle_shoulder)*(shoulder_motion$wing_CGy-shoulder_motion$pt1_Y)) + shoulder_motion$pt1_Y
shoulder_motion$backwards_CGx = (shoulder_motion$rest_m*shoulder_motion$rest_CGx + 2*shoulder_motion$wing_m*new_wing_CGx)/shoulder_motion$full_m

shoulder_motion$forward_CGx_specific   = (shoulder_motion$forward_CGx-shoulder_motion$pt1_X)/shoulder_motion$full_length
shoulder_motion$backwards_CGx_specific = (shoulder_motion$backwards_CGx-shoulder_motion$pt1_X)/shoulder_motion$full_length
shoulder_motion$range_CGx              = (shoulder_motion$forward_CGx-shoulder_motion$backwards_CGx)
shoulder_motion$range_CGx_specific     = shoulder_motion$range_CGx/(shoulder_motion$full_length)

# - Rotate the wing up about the shoulder in the y-z plane
new_wing_CGz = (cosd(angle_shoulder)*(shoulder_motion$wing_CGz-shoulder_motion$pt1_Z) - sind(angle_shoulder)*(shoulder_motion$wing_CGy-shoulder_motion$pt1_Y)) + shoulder_motion$pt1_Z
#new_wing_CGy = (sind(angle_shoulder)*(shoulder_motion$wing_CGz-shoulder_motion$pt1_Z) + cosd(angle_shoulder)*(shoulder_motion$wing_CGy-shoulder_motion$pt1_Y)) + shoulder_motion$pt1_Y
shoulder_motion$upwards_CGz   = (shoulder_motion$rest_m*shoulder_motion$rest_CGz + 2*shoulder_motion$wing_m*new_wing_CGz)/shoulder_motion$full_m

# - Rotate the wing down about the shoulder in the y-z plane
new_wing_CGz = (cosd(-angle_shoulder)*(shoulder_motion$wing_CGz-shoulder_motion$pt1_Z) - sind(-angle_shoulder)*(shoulder_motion$wing_CGy-shoulder_motion$pt1_Y)) + shoulder_motion$pt1_Z
#new_wing_CGy = (sind(-angle_shoulder)*(shoulder_motion$wing_CGz-shoulder_motion$pt1_Z) + cosd(-angle_shoulder)*(shoulder_motion$wing_CGy-shoulder_motion$pt1_Y)) + shoulder_motion$pt1_Y
shoulder_motion$downwards_CGz = (shoulder_motion$rest_m*shoulder_motion$rest_CGz + 2*shoulder_motion$wing_m*new_wing_CGz)/shoulder_motion$full_m

shoulder_motion$upwards_CGz_specific   = (shoulder_motion$upwards_CGz-shoulder_motion$pt1_Z)/shoulder_motion$full_length
shoulder_motion$downwards_CGz_specific = (shoulder_motion$downwards_CGz-shoulder_motion$pt1_Z)/shoulder_motion$full_length
shoulder_motion$range_CGz              = (shoulder_motion$downwards_CGz-shoulder_motion$upwards_CGz)
shoulder_motion$range_CGz_specific     = shoulder_motion$range_CGz/shoulder_motion$full_length
shoulder_motion$span_ratio             = shoulder_motion$b_max/shoulder_motion$full_length
shoulder_motion                        = mutate(shoulder_motion, phylo = binomial)

### ---------------------- Compute manuevering metrics -------------------------
# calculate the estimated neutral point using the quarter chord position of the standard mean chord
# the negative is necessary for the bird frame of reference as the orginal fit is to the absolute of the numbers
# this line is equivalent to x_np = (x_chord/c_root)^0.8*c_root
dat_final$x_np_est_orgShoulder = -(abs(dat_final$x_np_proxy_nd)^0.8)*dat_final$c_root_max
# we want the computed neutral point to be in the same direction as the standard mean quarter chord
# i.e. the neutral point should be positive if the standard mean quarter chord is positive
dat_final$x_np_est_orgShoulder[which(dat_final$x_np_proxy_nd > 0)] = -dat_final$x_np_est_orgShoulder[which(dat_final$x_np_proxy_nd > 0)]

## ------------ Stablity -----------
dat_final$sm    <- dat_final$full_CGx_orgShoulder-dat_final$x_np_est_orgShoulder
dat_final$sm_nd <- dat_final$sm/dat_final$c_root_max

## ------------ Agility -----------
dat_final$prop_q_dot     <- (-dat_final$sm*dat_final$S_max*dat_final$full_m^0.24)/dat_final$full_Iyy
dat_final$prop_q_dot_nd  <- (-dat_final$sm*dat_final$S_max*dat_final$full_length^2)/dat_final$full_Iyy
# uses scaling from: Alerstam, T., Rosén, M., Bäckman, J., Ericson, P. G., & Hellgren, O. (2007).
# Flight speeds among bird species: allometric and phylogenetic effects. PLoS Biol, 5(8), e197.

dat_final$sachs_pred_Ixx <- dat_final$full_m*(sqrt((0.14*dat_final$wing_m/dat_final$full_m))*dat_final$span*0.5)^2

## ----------- Tail Volume ------------
# CAUTION: THIS IS NON-DIMENSIONALIZED WITH THE MAXIMUM MEAN CHORD TO COMPARE TO TRADITIONAL AIRCRAFT
# absolute is just to get the absolute distance
dat_final$Vh = abs(-(dat_final$torso_length+0.25*dat_final$tail_length)-dat_final$full_CGx)*(dat_final$tail_length*dat_final$tail_width)/(dat_final$c_mean_mean*2*dat_final$S)

## ---- Compute the regression coefficients for each species for each variable -------

no_specimens <- nrow(dat_bird)
dat_model_out        <- data.frame(matrix(nrow = no_specimens*9*2, ncol = 5))
names(dat_model_out) <- c("species","model_variable","elb","man","elbman")
varlist_sp       <- c("full_Ixx_specific","full_Iyy_specific","full_Izz_specific","full_Ixz_specific",
                   "full_CGx_specific_orgBeak","full_CGx_specific_orgShoulder","wing_CGy_specific_orgShoulder","full_CGz_specific_orgDorsal","wing_CGx_specific_orgBeak")
short_varlist_sp <- c("Ixx_sp","Iyy_sp","Izz_sp","Ixz_sp","CGx_sp","CGx_sp_sh","CGy_sp","CGz_sp","CGx_wing_sp")
varlist_abs      <- c("full_Ixx","full_Iyy","full_Izz","full_Ixz",
                      "full_CGx_orgBeak","full_CGx_orgShoulder","wing_CGy_orgShoulder","full_CGz","wing_CGx")
short_varlist_abs<- c("Ixx","Iyy","Izz","Ixz",
                      "CGx","CGx_sh","CGy","CGz", "CGx_wing")
dat_bird$species <- as.character(dat_bird$species)
success = TRUE
count = 1
for (i in 1:no_specimens){
  # subset data to the current species
  tmp = subset(dat_final, species == dat_bird$species[i] & BirdID == dat_bird$BirdID[i])
  tmp$elbow_centered = tmp$elbow-mean(tmp$elbow)
  tmp$manus_centered = tmp$manus-mean(tmp$manus)
  for (m in 1:2){

    if(m == 1){
      varlist = varlist_abs
      short_varlist = short_varlist_abs
    } else{
      varlist = varlist_sp
      short_varlist = short_varlist_sp
    }

    # --------------- Fit models ------------------
    # full models
    models <- lapply(varlist, function(x) {lm(substitute(k ~ elbow_scaled*manus_scaled, list(k = as.name(x))), data = tmp)})
    # compute the effect size from the centered values of elbow and wrist to avoid conflating the differences between species in absolute range
    models_adj <- lapply(varlist, function(x) {lm(substitute(k*100 ~ elbow_centered*manus_centered, list(k = as.name(x))), data = tmp)})

    CI_values      = lapply(models, confint)
    coef_values    = lapply(models, coef)
    # Compute the effect size
    etap_values    = lapply(models_adj, function(x){eta_squared(car::Anova(x, type = 3))}) # partial = TRUE by default
    count2 = 1
    for (j in 1:length(models)){
      dat_model_out$species[count]        <- dat_bird$species[i]
      dat_model_out$BirdID[count]         <- dat_bird$BirdID[i]
      dat_model_out$model_variable[count] <- short_varlist[j]
      dat_model_out$int[count]            <- coef_values[[j]]["(Intercept)"]
      dat_model_out$elb[count]            <- coef_values[[j]]["elbow_scaled"]
      dat_model_out$man[count]            <- coef_values[[j]]["manus_scaled"]
      dat_model_out$r2[count]             <- summary(models[[j]])$r.squared
      dat_model_out$elb_p[count]          <- summary(models[[j]])$coefficients["elbow_scaled",4]
      dat_model_out$man_p[count]          <- summary(models[[j]])$coefficients["manus_scaled",4]
      dat_model_out$elbman_p[count]       <- summary(models[[j]])$coefficients["elbow_scaled:manus_scaled",4]
      dat_model_out$elbman[count]         <- coef_values[[j]]["elbow_scaled:manus_scaled"]
      dat_model_out$int_lb[count]         <- CI_values[[j]]["(Intercept)",1]
      dat_model_out$elb_lb[count]         <- CI_values[[j]]["elbow_scaled",1]
      dat_model_out$man_lb[count]         <- CI_values[[j]]["manus_scaled",1]
      dat_model_out$elbman_lb[count]      <- CI_values[[j]]["elbow_scaled:manus_scaled",1]
      dat_model_out$int_ub[count]         <- CI_values[[j]]["(Intercept)",2]
      dat_model_out$elb_ub[count]         <- CI_values[[j]]["elbow_scaled",2]
      dat_model_out$man_ub[count]         <- CI_values[[j]]["manus_scaled",2]
      dat_model_out$elbman_ub[count]      <- CI_values[[j]]["elbow_scaled:manus_scaled",2]
      # Compute the effect sizes
      dat_model_out$elb_etap[count]        <- etap_values[[j]][1,2]
      dat_model_out$man_etap[count]        <- etap_values[[j]][2,2]
      dat_model_out$elbman_etap[count]     <- etap_values[[j]][3,2]
      count = count + 1
    }
  }
}

tmp           = reshape2::melt(dat_model_out, id = c("species","BirdID","model_variable"))
dat_model_out = reshape2::dcast(tmp, species + BirdID ~ model_variable + variable, value.var="value")

# Include basic geometry effects
tmp       = aggregate(list(full_m = dat_bird$full_m),  by=list(species = dat_bird$species, binomial = dat_bird$binomial, BirdID = dat_bird$BirdID), mean)
dat_comp  = merge(tmp, dat_model_out, by = c("species","BirdID"))
dat_model_out  = merge(tmp, dat_model_out, by = c("species","BirdID"))
tmp       = aggregate(list(torsotail_length = dat_bird$torsotail_length),  by=list(species = dat_bird$species, BirdID = dat_bird$BirdID), mean)
dat_comp  = merge(dat_comp, tmp, by = c("species","BirdID"))

# Include other important factors
# Range of each component - doesn't matter where the origin is for the range
test     <- aggregate(list(range_CGx               = dat_final$full_CGx,
                           range_CGx_specific      = dat_final$full_CGx_specific_orgBeak,
                           range_wing_CGy          = dat_final$wing_CGy,
                           range_wing_CGy_specific = dat_final$wing_CGy_specific,
                           range_CGz               = dat_final$full_CGz,
                           range_CGz_specific      = dat_final$full_CGz_specific_orgDorsal,
                           range_Ixx               = dat_final$full_Ixx,
                           range_Ixx_specific      = dat_final$full_Ixx_specific,
                           range_Iyy               = dat_final$full_Iyy,
                           range_Iyy_specific      = dat_final$full_Iyy_specific,
                           range_Izz               = dat_final$full_Izz,
                           range_Izz_specific      = dat_final$full_Izz_specific),
                      by=list(species = dat_final$species, BirdID = dat_final$BirdID), FUN=function(x){max(x)-min(x)})
dat_comp <- merge(dat_comp,test, by = c("species","BirdID"))

# Include other important factors
# Range of each component
test     <- aggregate(list(mean_CGx_orgBeak      = dat_final$full_CGx_orgBeak,
                           mean_CGz_orgDorsal    = dat_final$full_CGz_orgDorsal,
                           mean_CGx_orgShoulder  = dat_final$full_CGx_orgShoulder,
                           mean_CGz_orgShoulder  = dat_final$full_CGz_orgShoulder,
                           mean_wing_CGy                 = dat_final$wing_CGy_orgShoulder,
                           mean_CGx_specific_orgBeak     = dat_final$full_CGx_specific_orgBeak,
                           mean_CGz_specific_orgDorsal   = dat_final$full_CGz_specific_orgDorsal,
                           mean_CGx_specific_orgShoulder = dat_final$full_CGx_specific_orgShoulder,
                           mean_CGz_specific_orgShoulder = dat_final$full_CGz_specific_orgShoulder,
                           mean_wing_CGy_specific        = dat_final$wing_CGy_specific_orgShoulder,
                           mean_Ixx_specific = dat_final$full_Ixx_specific,
                           mean_Iyy_specific = dat_final$full_Iyy_specific,
                           mean_Izz_specific = dat_final$full_Izz_specific,
                           mean_Ixz_specific = dat_final$full_Ixz_specific,
                           mean_Ixx          = dat_final$full_Ixx,
                           mean_Iyy          = dat_final$full_Iyy,
                           mean_Izz          = dat_final$full_Izz,
                           mean_Ixz          = dat_final$full_Ixz,
                           full_length       = dat_final$full_length), # noote that this isn't actually a mean just pulling out each specimen's length
                      by=list(species = dat_final$species, BirdID = dat_final$BirdID), mean)
dat_comp <- merge(dat_comp,test, by = c("species","BirdID"))
# Maximum values
test     <- aggregate(list(max_CGx_orgBeak       = dat_final$full_CGx_orgBeak,
                           max_CGz_orgDorsal     = dat_final$full_CGz_orgDorsal,
                           max_CGx_specific      = dat_final$full_CGx_specific_orgBeak,
                           max_CGx_orgShoulder   = dat_final$full_CGx_orgShoulder,
                           max_wing_CGy          = dat_final$wing_CGy_orgShoulder,
                           max_wing_CGy_specific = dat_final$wing_CGy_specific_orgShoulder,
                           max_CGz_specific      = dat_final$full_CGz_specific_orgDorsal,
                           max_Ixx               = dat_final$full_Ixx,
                           max_wing_Ixx          = dat_final$wing_Ixx,
                           sachs_pred_Ixx        = dat_final$sachs_pred_Ixx,
                           max_Ixx_specific      = dat_final$full_Ixx_specific,
                           max_Iyy               = dat_final$full_Iyy,
                           max_Iyy_specific      = dat_final$full_Iyy_specific,
                           max_Izz               = dat_final$full_Izz,
                           max_Izz_specific      = dat_final$full_Izz_specific,
                           max_Ixz_specific      = dat_final$full_Ixz_specific,
                           max_q                 = dat_final$prop_q_dot,
                           max_q_nd              = dat_final$prop_q_dot_nd,
                           max_wingspan          = dat_final$span,
                           max_length            = dat_final$full_length,
                           max_S                 = dat_final$S_max,
                           max_S_proj            = dat_final$S_proj_max,
                           max_Vh                = dat_final$Vh,
                           max_sm                = dat_final$sm,
                           max_sm_nd             = dat_final$sm_nd,
                           max_armhand_ratio     = dat_final$arm_span/dat_final$hand_span),
                      by=list(species = dat_final$species, BirdID = dat_final$BirdID), max)
dat_comp <- merge(dat_comp,test, by = c("species","BirdID"))
# Minimum values
test     <- aggregate(list(min_CGx_orgBeak       = dat_final$full_CGx_orgBeak,
                           min_CGz_orgDorsal     = dat_final$full_CGz_orgDorsal,
                           min_CGx_specific      = dat_final$full_CGx_specific_orgBeak,
                           min_CGx_orgShoulder   = dat_final$full_CGx_orgShoulder,
                           min_wing_CGy          = dat_final$wing_CGy_orgShoulder,
                           min_wing_CGy_specific = dat_final$wing_CGy_specific_orgShoulder,
                           min_CGz_specific      = dat_final$full_CGz_specific_orgDorsal,
                           min_wing_Ixx          = dat_final$wing_Ixx,
                           min_Ixx               = dat_final$full_Ixx,
                           min_Ixx_specific      = dat_final$full_Ixx_specific,
                           min_Iyy               = dat_final$full_Iyy,
                           min_Iyy_specific      = dat_final$full_Iyy_specific,
                           min_Izz               = dat_final$full_Izz,
                           min_q                 = dat_final$prop_q_dot,
                           min_q_nd              = dat_final$prop_q_dot_nd,
                           min_wingspan          = dat_final$span,
                           min_Izz_specific      = dat_final$full_Izz_specific,
                           min_Ixz_specific      = dat_final$full_Ixz_specific,
                           hum_len               = (dat_final$humerus_length_mm+dat_final$ulna_length_mm+dat_final$radius_length_mm+dat_final$cmc_length_mm),
                           min_sm                = dat_final$sm,
                           min_sm_nd             = dat_final$sm_nd),
                      by=list(species = dat_final$species, BirdID = dat_final$BirdID), min)
dat_comp <- merge(dat_comp,test, by = c("species","BirdID"))

dat_comp$max_wing_CGx <- dat_final$wing_CGx[which((dat_final$wing_CGy - dat_final$pt1_Y) %in% dat_comp$max_wing_CGy)]
dat_comp$max_wing_CGx_specific <- dat_final$wing_CGx_specific_orgShoulder[which((dat_final$wing_CGy - dat_final$pt1_Y) %in% dat_comp$max_wing_CGy)]

dat_comp$sm_range   = dat_comp$max_sm_nd - dat_comp$min_sm_nd
dat_comp$q_range    = dat_comp$max_q - dat_comp$min_q
dat_comp$q_nd_range = dat_comp$max_q_nd - dat_comp$min_q_nd

# --------- Trim the trees -----------
# critical for PGLS models
dat_comp <- mutate(dat_comp, phylo = binomial)
## Prune down the tree to the relevant species
sp_mean_matched <- keep.tip(phy = full_tree, tip = dat_comp$binomial)
## ladderization rotates nodes to make it easier to see basal vs derived
pruned_mcc      <- ape::ladderize(sp_mean_matched)
# plot plot(pruned_mcc)
## The phylogeny will need to be re-formatted for use within MCMCglmm
inv.phylo <- inverseA(pruned_mcc, nodes = "TIPS", scale = TRUE)
## This is the heirarcy of the univariate prior.
univ_prior <-
  list(G = list(G1 = list(V = 1, nu = 0.02)),
       R = list(V = 1, nu = 0.02))


# to compute Pagels lambda - (pgls_model_mcmc$VCV[, 1] / (pgls_model_mcmc$VCV[, 1] + pgls_model_mcmc$VCV[, 2])) %>% mean

# filename = paste(format(Sys.Date(), "%Y_%m_%d"),"_alldata.csv",sep="")
# write.csv(dat_final,filename)
# filename = paste(format(Sys.Date(), "%Y_%m_%d"),"_compdata.csv",sep="")
# write.csv(dat_comp,filename)
charvey23/AvInertia documentation built on April 14, 2022, 1:09 p.m.