---
title: "An evolvable celestial homing mechanism - Code"
author: "Yuval Werber"
date: "2026-07-26"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(root.dir="")
setwd("")
library(pracma)
library(suncalc)
library(tidyverse)
library(dplyr)
library(hms)
library(geosphere)
library(circular)
library(RcppAlgos)
library(ggpubr)
library(cowplot)
library(ggnewscale)
```
Preparing simulation datasets
```{r}
#Randomly sample each vector along the relevant tange and then join them manually
##Lats and Lons
Latitude_displacement<-round(runif(n = 1000000, min = 0, max = 90),digits=2)
Longitude_displacement<-round(runif(n = 1000000, min = 0, max = 180),digits=2)
Distance<-round(runif(n = 1000000, min = 0, max = 100000),digits=0)#in meters
azimuth<-round(runif(n = 1000000, min = 0, max = 359.99),digits=2)
##Date_time
# 1. Define start and end times
start_time <- as.POSIXct("2023-01-01 00:00:00", tz = "UTC")
end_time <- as.POSIXct("2024-01-01 00:00:00", tz = "UTC")
# 2. Define the number of random timestamps you need
n_timestamps <- 1000000
# 3. Set a seed for reproducibility (optional)
set.seed(123)
# 4. Generate 'n' random numbers (seconds) between the integer representation of
# start and end times using runif()
random_seconds <- runif(n = n_timestamps,
min = as.numeric(start_time),
max = as.numeric(end_time))
# 5. Convert the random seconds back to POSIXct format
random_timestamps <- as.POSIXct(random_seconds, origin = "1970-01-01", tz = "UTC")
# 6. Create a data frame with the new column
df <- data.frame(
id = 1:n_timestamps,
timestamp = random_timestamps
)
Date_time<-df$timestamp
Time_shift<-round(runif(n = 1000000, min = -6, max = 6),digits=0)
##Raw table-using expand grid not scaleable because makes enormous tables
#This seems to break at wider ranges of longitue, test whiy this is
##First trial - 0-90 Lat, 0-40 lon
Table<-data.frame(Latitude_displacement=Latitude_displacement,Longitude_displacement=Longitude_displacement,Distance=Distance,azimuth=azimuth,Date_time=Date_time,Time_shift=Time_shift)
#Table<-expand.grid(Latitude_displacement = seq(0,90,10), Longitude_displacement = seq(0, 180,10),
# Date_time=seq(from = start_time, to = end_time, by = "1 hour"),Time_shift=seq(from =0, to=6,by=1))
#set.seed(10)
#Table$Latitude_home<-sample(Table$Latitude_displacement)
#Table$Longitude_home<-sample(Table$Longitude_displacement)
Table$time_epoch<-as.numeric(Table$Date_time)
##Make a date column
Table$Date<-as.Date(Table$Date_time)
# Convert to an hms object (only stores time internally, uses a dummy date)
Table$Hour<- as_hms(Table$Date_time)
# Calculate destination points
destination_points <- destPoint(
p = cbind(Table$Longitude_displacement, Table$Latitude_displacement),
b = Table$azimuth,
d = Table$Distance
)
destination_points<-as.data.frame(destination_points)
Table$Latitude_home<-destination_points$lat
Table$Longitude_home<-destination_points$lon
Table<-Table[c(10,11,1:9)]
Table$Distance_km<-Table$Distance/1000
##Get sunrise and sunset tHour##Get sunrise and sunset times
lat<-Table$Latitude_displacement
lon<-Table$Longitude_displacement
date<-Table$Date
Sun_phase_prep_table <- data.frame(cbind(date,lat,lon))
Sun_phase_prep_table$date <- as.Date(Sun_phase_prep_table$date, origin="1970-01-01")
Sun_phase_table <- getSunlightTimes(data =
Sun_phase_prep_table, tz = "UTC", keep = c("sunrise", "sunset"))
Table$Sunrise<-Sun_phase_table$sunrise
Table$sunrise_epoch<-as.numeric(Table$Sunrise)
Table$Sunset<-Sun_phase_table$sunset
Table$sunset_epoch<-as.numeric(Table$Sunset)
##Calculate day length
Table$Day_length<-difftime(Table$Sunset, Table$Sunrise, units = "hours")
Table$Day_length<-as.numeric(Table$Day_length)
##Calculate Day/night
Table$Daynight<-ifelse(Table$time_epoch
Table$sunset_epoch,"Night","Day")
Table<-Table%>%filter(Daynight=="Day")
##Calculate time from sunrise
Table$Time_from_sunrise<-difftime(Table$Date_time, Table$Sunrise, units = "hours")
Table$Time_from_sunrise<-as.numeric(Table$Time_from_sunrise)
##Calculate the observed hour angle based on the Expected formula (which uses time) and the difference in longitude between displacement and home.
Table$Observed_hour_angle<-Table$Time_from_sunrise*180/Table$Day_length+(Table$Longitude_displacement-Table$Longitude_home)
##Filter only home-displacement combinations that produce obsered hour angles between 0-180, below which and above which the sun is not in the sky
##at dispalcement. Expected hour angle doesnt need filtering becuase the forula restricts it to 0-180
Table<-Table%>%filter(as.numeric(Observed_hour_angle)>0)
Table<-Table%>%filter(as.numeric(Observed_hour_angle)<180)
Table$time_epoch<-NULL
Table$sunrise_epoch<-NULL
Table$sunset_epoch<-NULL
Table$Daynight<-NULL
#Table<-Table[,c(1,2,5,6,3,7,8,4,9:13)]
rm(Sun_phase_prep_table,Sun_phase_table,date,end_time,start_time,lat,lon,Latitude_displacement,Latitude_home,Longitude_displacement, Longitude_home,df,n_timestamps,Date_time,random_seconds,random_timestamps,Time_shift,destination_points,azimuth,Distance)
##Add distance in km and 3 azimuth types using the geosphere package as reference to compare the output of our functions
# 1. Calculate the distance (in meters by default)
# Use distGeo for the most accurate ellipsoidal distance
library(geosphere)
library(dplyr)
#For northern Hemisphere
# Calculate the distance for each row
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(distance_km_geo = as.numeric(distGeo(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))/1000)) %>%
ungroup() # Return to a standard data frame
# Calculate the distance for each row
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(distance_km_rhumb_geo = as.numeric(distRhumb(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))/1000)) %>%
ungroup() # Return to a standard data frame
# 2. Calculate the initial azimuth (bearing in degrees from North)
# The bearing function returns the initial bearing
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(Azimuth_initial_geo = ?bearing(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))) %>%
ungroup() # Return to a standard data frame
Table$Azimuth_initial_geo <- (Table$Azimuth_initial_geo + 360) %% 360
# 3. Calculate the final azimuth (bearing when arriving at the destination)
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(Azimuth_final_geo = finalBearing(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))) %>%
ungroup() # Return to a standard data frame
Table$Azimuth_final_geo <- (Table$Azimuth_final_geo + 360) %% 360
# 4. Calculate the Rhump azimuth (the bearing of the rhumb line- a line that will bring the animal home in a fixed azimuth)
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(Azimuth_rhumb_geo = bearingRhumb(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))) %>%
ungroup() # Return to a standard data frame
Table$Azimuth_rhumb_geo <- (Table$Azimuth_rhumb_geo + 360) %% 360
Table_100<-Table
Table_100$range<-rep(100,nrow(Table_100))
#1000 km
#Think of a way to creare a table without producing all the combinations:
#Randomly sample each vector along the relevant tange and then join them manually
##Lats and Lons
Latitude_displacement<-round(runif(n = 1000000, min = 0, max = 90),digits=2)
Longitude_displacement<-round(runif(n = 1000000, min = 0, max = 180),digits=2)
Distance<-round(runif(n = 1000000, min = 100000, max = 1000000),digits=0)#in meters
azimuth<-round(runif(n = 1000000, min = 0, max = 359.99),digits=2)
##Date_time
# 1. Define start and end times
start_time <- as.POSIXct("2023-01-01 00:00:00", tz = "UTC")
end_time <- as.POSIXct("2024-01-01 00:00:00", tz = "UTC")
# 2. Define the number of random timestamps you need
n_timestamps <- 1000000
# 3. Set a seed for reproducibility (optional)
set.seed(123)
# 4. Generate 'n' random numbers (seconds) between the integer representation of
# start and end times using runif()
random_seconds <- runif(n = n_timestamps,
min = as.numeric(start_time),
max = as.numeric(end_time))
# 5. Convert the random seconds back to POSIXct format
random_timestamps <- as.POSIXct(random_seconds, origin = "1970-01-01", tz = "UTC")
# 6. Create a data frame with the new column
df <- data.frame(
id = 1:n_timestamps,
timestamp = random_timestamps
)
Date_time<-df$timestamp
Time_shift<-round(runif(n = 1000000, min = -6, max = 6),digits=0)
##Raw table-using expand grid not scaleable because makes enormous tables
#This seems to break at wider ranges of longitue, test whiy this is
##First trial - 0-90 Lat, 0-40 lon
Table<-data.frame(Latitude_displacement=Latitude_displacement,Longitude_displacement=Longitude_displacement,Distance=Distance,azimuth=azimuth,Date_time=Date_time,Time_shift=Time_shift)
#Table<-expand.grid(Latitude_displacement = seq(0,90,10), Longitude_displacement = seq(0, 180,10),
# Date_time=seq(from = start_time, to = end_time, by = "1 hour"),Time_shift=seq(from =0, to=6,by=1))
#set.seed(10)
#Table$Latitude_home<-sample(Table$Latitude_displacement)
#Table$Longitude_home<-sample(Table$Longitude_displacement)
Table$time_epoch<-as.numeric(Table$Date_time)
##Make a date column
Table$Date<-as.Date(Table$Date_time)
# Convert to an hms object (only stores time internally, uses a dummy date)
Table$Hour<- as_hms(Table$Date_time)
# Calculate destination points
destination_points <- destPoint(
p = cbind(Table$Longitude_displacement, Table$Latitude_displacement),
b = Table$azimuth,
d = Table$Distance
)
destination_points<-as.data.frame(destination_points)
Table$Latitude_home<-destination_points$lat
Table$Longitude_home<-destination_points$lon
Table<-Table[c(10,11,1:9)]
Table$Distance_km<-Table$Distance/1000
##Get sunrise and sunset tHour##Get sunrise and sunset times
lat<-Table$Latitude_displacement
lon<-Table$Longitude_displacement
date<-Table$Date
Sun_phase_prep_table <- data.frame(cbind(date,lat,lon))
Sun_phase_prep_table$date <- as.Date(Sun_phase_prep_table$date, origin="1970-01-01")
Sun_phase_table <- getSunlightTimes(data =
Sun_phase_prep_table, tz = "UTC", keep = c("sunrise", "sunset"))
Table$Sunrise<-Sun_phase_table$sunrise
Table$sunrise_epoch<-as.numeric(Table$Sunrise)
Table$Sunset<-Sun_phase_table$sunset
Table$sunset_epoch<-as.numeric(Table$Sunset)
##Calculate day length
Table$Day_length<-difftime(Table$Sunset, Table$Sunrise, units = "hours")
Table$Day_length<-as.numeric(Table$Day_length)
##Calculate Day/night
Table$Daynight<-ifelse(Table$time_epochTable$sunset_epoch,"Night","Day")
Table<-Table%>%filter(Daynight=="Day")
##Calculate time from sunrise
Table$Time_from_sunrise<-difftime(Table$Date_time, Table$Sunrise, units = "hours")
Table$Time_from_sunrise<-as.numeric(Table$Time_from_sunrise)
##Calculate the observed hour angle based on the Expected formula (which uses time) and the difference in longitude between displacement and home.
Table$Observed_hour_angle<-Table$Time_from_sunrise*180/Table$Day_length+(Table$Longitude_displacement-Table$Longitude_home)
##Filter only home-displacement combinations that produce obsered hour angles between 0-180, below which and above which the sun is not in the sky
##at dispalcement. Expected hour angle doesnt need filtering becuase the forula restricts it to 0-180
Table<-Table%>%filter(as.numeric(Observed_hour_angle)>0)
Table<-Table%>%filter(as.numeric(Observed_hour_angle)<180)
Table$time_epoch<-NULL
Table$sunrise_epoch<-NULL
Table$sunset_epoch<-NULL
Table$Daynight<-NULL
#Table<-Table[,c(1,2,5,6,3,7,8,4,9:13)]
rm(Sun_phase_prep_table,Sun_phase_table,date,end_time,start_time,lat,lon,Latitude_displacement,Latitude_home,Longitude_displacement, Longitude_home,df,n_timestamps,Date_time,random_seconds,random_timestamps,Time_shift,destination_points,azimuth,Distance)
##Add distance in km and 3 azimuth types using the geosphere package as reference to compare the output of our functions
# 1. Calculate the distance (in meters by default)
# Use distGeo for the most accurate ellipsoidal distance
library(geosphere)
library(dplyr)
# Calculate the distance for each row
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(distance_km_geo = as.numeric(distGeo(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))/1000)) %>%
ungroup() # Return to a standard data frame
# Calculate the distance for each row
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(distance_km_rhumb_geo = as.numeric(distRhumb(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))/1000)) %>%
ungroup() # Return to a standard data frame
# 2. Calculate the initial azimuth (bearing in degrees from North)
# The bearing function returns the initial bearing
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(Azimuth_initial_geo = bearing(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))) %>%
ungroup() # Return to a standard data frame
Table$Azimuth_initial_geo <- (Table$Azimuth_initial_geo + 360) %% 360
# 3. Calculate the final azimuth (bearing when arriving at the destination)
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(Azimuth_final_geo = finalBearing(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))) %>%
ungroup() # Return to a standard data frame
Table$Azimuth_final_geo <- (Table$Azimuth_final_geo + 360) %% 360
# 4. Calculate the Rhump azimuth (the bearing of the rhumb line- a line that will bring the animal home in a fixed azimuth)
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(Azimuth_rhumb_geo = bearingRhumb(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))) %>%
ungroup() # Return to a standard data frame
Table$Azimuth_rhumb_geo <- (Table$Azimuth_rhumb_geo + 360) %% 360
Table_1000<-Table
Table_1000$range<-rep(1000,nrow(Table_1000))
##20000 km
#Think of a way to creare a table without producing all the combinations:
#Randomly sample each vector along the relevant tange and then join them manually
##Lats and Lons
Latitude_displacement<-round(runif(n = 1000000, min = 0, max = 90),digits=2)
Longitude_displacement<-round(runif(n = 1000000, min = 0, max = 180),digits=2)
Distance<-round(runif(n = 1000000, min = 1000000, max = 20000000),digits=0)#in meters
azimuth<-round(runif(n = 1000000, min = 0, max = 359.99),digits=2)
##Date_time
# 1. Define start and end times
start_time <- as.POSIXct("2023-01-01 00:00:00", tz = "UTC")
end_time <- as.POSIXct("2024-01-01 00:00:00", tz = "UTC")
# 2. Define the number of random timestamps you need
n_timestamps <- 1000000
# 3. Set a seed for reproducibility (optional)
set.seed(123)
# 4. Generate 'n' random numbers (seconds) between the integer representation of
# start and end times using runif()
random_seconds <- runif(n = n_timestamps,
min = as.numeric(start_time),
max = as.numeric(end_time))
# 5. Convert the random seconds back to POSIXct format
random_timestamps <- as.POSIXct(random_seconds, origin = "1970-01-01", tz = "UTC")
# 6. Create a data frame with the new column
df <- data.frame(
id = 1:n_timestamps,
timestamp = random_timestamps
)
Date_time<-df$timestamp
Time_shift<-round(runif(n = 1000000, min = -6, max = 6),digits=0)
##Raw table-using expand grid not scaleable because makes enormous tables
#This seems to break at wider ranges of longitue, test whiy this is
##First trial - 0-90 Lat, 0-40 lon
Table<-data.frame(Latitude_displacement=Latitude_displacement,Longitude_displacement=Longitude_displacement,Distance=Distance,azimuth=azimuth,Date_time=Date_time,Time_shift=Time_shift)
#Table<-expand.grid(Latitude_displacement = seq(0,90,10), Longitude_displacement = seq(0, 180,10),
# Date_time=seq(from = start_time, to = end_time, by = "1 hour"),Time_shift=seq(from =0, to=6,by=1))
#set.seed(10)
#Table$Latitude_home<-sample(Table$Latitude_displacement)
#Table$Longitude_home<-sample(Table$Longitude_displacement)
Table$time_epoch<-as.numeric(Table$Date_time)
##Make a date column
Table$Date<-as.Date(Table$Date_time)
# Convert to an hms object (only stores time internally, uses a dummy date)
Table$Hour<- as_hms(Table$Date_time)
# Calculate destination points
destination_points <- destPoint(
p = cbind(Table$Longitude_displacement, Table$Latitude_displacement),
b = Table$azimuth,
d = Table$Distance
)
destination_points<-as.data.frame(destination_points)
Table$Latitude_home<-destination_points$lat
Table$Longitude_home<-destination_points$lon
Table<-Table[c(10,11,1:9)]
Table$Distance_km<-Table$Distance/1000
##Get sunrise and sunset tHour##Get sunrise and sunset times
lat<-Table$Latitude_displacement
lon<-Table$Longitude_displacement
date<-Table$Date
Sun_phase_prep_table <- data.frame(cbind(date,lat,lon))
Sun_phase_prep_table$date <- as.Date(Sun_phase_prep_table$date, origin="1970-01-01")
Sun_phase_table <- getSunlightTimes(data =
Sun_phase_prep_table, tz = "UTC", keep = c("sunrise", "sunset"))
Table$Sunrise<-Sun_phase_table$sunrise
Table$sunrise_epoch<-as.numeric(Table$Sunrise)
Table$Sunset<-Sun_phase_table$sunset
Table$sunset_epoch<-as.numeric(Table$Sunset)
##Calculate day length
Table$Day_length<-difftime(Table$Sunset, Table$Sunrise, units = "hours")
Table$Day_length<-as.numeric(Table$Day_length)
##Calculate Day/night
Table$Daynight<-ifelse(Table$time_epochTable$sunset_epoch,"Night","Day")
Table<-Table%>%filter(Daynight=="Day")
##Calculate time from sunrise
Table$Time_from_sunrise<-difftime(Table$Date_time, Table$Sunrise, units = "hours")
Table$Time_from_sunrise<-as.numeric(Table$Time_from_sunrise)
##Calculate the observed hour angle based on the Expected formula (which uses time) and the difference in longitude between displacement and home.
Table$Observed_hour_angle<-Table$Time_from_sunrise*180/Table$Day_length+(Table$Longitude_displacement-Table$Longitude_home)
##Filter only home-displacement combinations that produce obsered hour angles between 0-180, below which and above which the sun is not in the sky
##at dispalcement. Expected hour angle doesnt need filtering becuase the forula restricts it to 0-180
Table<-Table%>%filter(as.numeric(Observed_hour_angle)>0)
Table<-Table%>%filter(as.numeric(Observed_hour_angle)<180)
Table$time_epoch<-NULL
Table$sunrise_epoch<-NULL
Table$sunset_epoch<-NULL
Table$Daynight<-NULL
#Table<-Table[,c(1,2,5,6,3,7,8,4,9:13)]
rm(Sun_phase_prep_table,Sun_phase_table,date,end_time,start_time,lat,lon,Latitude_displacement,Latitude_home,Longitude_displacement, Longitude_home,df,n_timestamps,Date_time,random_seconds,random_timestamps,Time_shift,destination_points,azimuth,Distance)
##Add distance in km and 3 azimuth types using the geosphere package as reference to compare the output of our functions
# 1. Calculate the distance (in meters by default)
# Use distGeo for the most accurate ellipsoidal distance
library(geosphere)
library(dplyr)
# Calculate the distance for each row
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(distance_km_geo = as.numeric(distGeo(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))/1000)) %>%
ungroup() # Return to a standard data frame
# Calculate the distance for each row
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(distance_km_rhumb_geo = as.numeric(distRhumb(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))/1000)) %>%
ungroup() # Return to a standard data frame
# 2. Calculate the initial azimuth (bearing in degrees from North)
# The bearing function returns the initial bearing
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(Azimuth_initial_geo = bearing(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))) %>%
ungroup() # Return to a standard data frame
Table$Azimuth_initial_geo <- (Table$Azimuth_initial_geo + 360) %% 360
# 3. Calculate the final azimuth (bearing when arriving at the destination)
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(Azimuth_final_geo = finalBearing(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))) %>%
ungroup() # Return to a standard data frame
Table$Azimuth_final_geo <- (Table$Azimuth_final_geo + 360) %% 360
# 4. Calculate the Rhump azimuth (the bearing of the rhumb line- a line that will bring the animal home in a fixed azimuth)
Table <- Table %>%
dplyr::rowwise() %>% # perform the operation row by row
dplyr::mutate(Azimuth_rhumb_geo = bearingRhumb(p1 = c(Longitude_displacement, Latitude_displacement),
p2 = c(Longitude_home, Latitude_home))) %>%
ungroup() # Return to a standard data frame
Table$Azimuth_rhumb_geo <- (Table$Azimuth_rhumb_geo + 360) %% 360
Table_20000<-Table
Table_20000$range<-rep(20000,nrow(Table_20000))
#Table<-rbind(Table_100,Table_1000,Table_20000)
#rm(Table)
```
##Now apply the functions for 100,000 simulations of each range separately, other wise it will crash to computer.
A chunck that defines all the functoin we want to test
For explanation about hte function go to script v4 and look by name
```{r}
#Full Binary function - No time shift:
########################################
#Parameter definition
#NCP_altitude_home<-as.circular(40, type = "angles", units ="degrees", template = "geographics")
#NCP_altitude_displacement<-as.circular(40, type = "angles", units ="degrees", template = "geographics")
#Day_length<-12#in hours
#Time_from_sunrise_at_displacement<-2#in hours
#Observed_hour_angle_displacement<-as.circular(30, type = "angles", units ="degrees", template = "geographics")
#Observed_hour_angle_displacement_no_shift<-as.circular(30, type = "angles", units ="degrees", template = "geographics")
#Time_shift<-1#in hours
#Function:
N_Binary_No_Shift<- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_correction<-as.circular(ifelse(NCP_altitude_displacement>NCP_altitude_home,180,ifelse(NCP_altitude_displacementExpected_hour_angle_displacement,270,NA)), type = "angles", units = "degrees", template = "geographics")# EW correction, NA marks Obsereved-Expected equivalence, meaning no correction needed
t<-mean.circular(as.circular(na.omit(c(NS_correction,EW_correction)), type = "angles", units = "degrees", template = "geographics"))#na.omit remove NAs from the mean calculation - because they signify ne correction needed on the relevant axis
return(ifelse(all(is.na(t)),"Home",ifelse( t>0,t,360+t))) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#Full Binary function - with time shift
########################################
#Time shift is integrated in the observed hour angle
N_Binary_Shifted <- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_correction<-as.circular(ifelse(NCP_altitude_displacement>NCP_altitude_home,180,ifelse(NCP_altitude_displacementExpected_hour_angle_displacement,270,NA)), type = "angles", units = "degrees", template = "geographics")# EW correction, NA marks Obsereved-Expected equivalence, meaning no correction needed
t<-mean.circular(as.circular(na.omit(c(NS_correction,EW_correction)), type = "angles", units = "degrees", template = "geographics"))#na.omit remove NAs from the mean calculation - because they signify ne correction needed on the relevant axis
return(ifelse(all(is.na(t)),"Home",ifelse( t>0,t,360+t))) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#Separate functions for North-South and East-West components
############################################################
#North-South component
######################
#Time shift is irrelevant for this compoonent
N_Binary_NS <- function(NCP_altitude_displacement,NCP_altitude_home) {
NS_correction<-as.circular(ifelse(NCP_altitude_displacement>NCP_altitude_home,180,ifelse(NCP_altitude_displacementExpected_hour_angle_displacement,270,NA)), type = "angles", units = "degrees", template = "geographics")# EW correction, NA marks Obsereved-Expected equivalence, meaning no correction needed
return(EW_correction)
}
#With time shift
###############
N_Binary_EW_Shifted <- function(Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length)
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
EW_correction<-as.circular(ifelse(Observed_hour_angle_displacementExpected_hour_angle_displacement,270,NA)), type = "angles", units = "degrees", template = "geographics")# EW correction, NA marks Obsereved-Expected equivalence, meaning no correction needed
return(EW_correction)
}
###############################################################
###############################################################
#VECTOR HOMING FUNCTIONS
###############################################################
###############################################################
#No time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
N_Vector_String_No_Shift <- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_distance<-as.numeric(abs(NCP_altitude_displacement-NCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(NCP_altitude_displacement>NCP_altitude_home,180,0), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(NCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-conversion.circular(as.circular(atan(NS_distance/EW_distance), type = "angles", units = "radians", template = "geographics"), type = "angles", units = "degrees", template = "geographics")#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
Homing_azimuth<-ifelse (NS_distance == 0 & EW_distance == 0,"Home",
ifelse(NS_distance == 0, EW_azimuth ,
ifelse (EW_distance == 0 , NS_azimuth,
as.circular(ifelse(EW_azimuth==90&NS_azimuth==0,90-alpha,
ifelse(EW_azimuth==90&NS_azimuth==180,90+alpha,
ifelse(EW_azimuth==270&NS_azimuth==0,270+alpha,270-alpha))), type = "angles", units = "degrees", template = "geographics"))))
#is the desired flight azimuth to get home on the shortest linear distance "Distance_to_home"
return(paste("Distance",Distance_to_home,"azimuth",Homing_azimuth)) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
N_Vector_String_No_Shift_atan2 <- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_distance<-as.numeric(NCP_altitude_home-NCP_altitude_displacement)*111 #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(NCP_altitude_displacement>NCP_altitude_home,180,0), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular( Expected_hour_angle_displacement-Observed_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(Hour_angle_diff*111.32*as.numeric(cos(NCP_altitude_displacement*pi/180)))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-atan2(EW_distance,NS_distance)#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
#Homing_azimuth<-(alpha*180/pi)+180
Homing_azimuth<-((alpha*180/pi) %% 360 + 360)%% 360
return(paste("Distance",Distance_to_home,"azimuth",Homing_azimuth)) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#No time shift - Separate function for distance to home and home azimuth for use is analysis
###########################################################################################
#Straight line distance to home function
#######################################
N_Vector_distance_No_Shift <- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_distance<-as.numeric(abs(NCP_altitude_displacement-NCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(NCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
return(Distance_to_home)# If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#Straight line azimuth home function
###################################
N_Vector_Azimuth_No_Shift <- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_distance<-as.numeric(abs(NCP_altitude_displacement-NCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(NCP_altitude_displacement>NCP_altitude_home,180,0), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(NCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-conversion.circular(as.circular(atan(NS_distance/EW_distance), type = "angles", units = "radians", template = "geographics"), type = "angles", units = "degrees", template = "geographics")#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
Homing_azimuth<-ifelse (NS_distance == 0 & EW_distance == 0,"Home",
ifelse(NS_distance == 0, EW_azimuth ,
ifelse (EW_distance == 0 , NS_azimuth,
as.circular(ifelse(EW_azimuth==90&NS_azimuth==0,90-alpha,
ifelse(EW_azimuth==90&NS_azimuth==180,90+alpha,
ifelse(EW_azimuth==270&NS_azimuth==0,270+alpha,270-alpha))), type = "angles", units = "degrees", template = "geographics"))))
#is the desired flight azimuth to get home on the shortest linear distance "Distance_to_home"
return(Homing_azimuth) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
N_Vector_Azimuth_No_Shift_atan2 <- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_distance<-as.numeric(NCP_altitude_home-NCP_altitude_displacement)*111 #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(NCP_altitude_displacement>NCP_altitude_home,180,0), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular( Expected_hour_angle_displacement-Observed_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(Hour_angle_diff*111.32*as.numeric(cos(NCP_altitude_displacement*pi/180)))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-atan2(EW_distance,NS_distance)#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
#Homing_azimuth<-(alpha*180/pi)+180
Homing_azimuth<-((alpha*180/pi) %% 360 + 360)%% 360
#is the desired flight azimuth to get home on the shortest linear distance "Distance_to_home"
return(Homing_azimuth) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#With time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
N_Vector_String_Shifted <- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_distance<-as.numeric(abs(NCP_altitude_displacement-NCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(NCP_altitude_displacement>NCP_altitude_home,180,0), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(NCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-conversion.circular(as.circular(atan(NS_distance/EW_distance), type = "angles", units = "radians", template = "geographics"), type = "angles", units = "degrees", template = "geographics")#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different calculation for each of the for component direction combinations
Homing_azimuth<-ifelse (NS_distance == 0 & EW_distance == 0,"Home",
ifelse(NS_distance == 0, EW_azimuth ,
ifelse (EW_distance == 0 , NS_azimuth,
as.circular(ifelse(EW_azimuth==90&NS_azimuth==0,90-alpha,
ifelse(EW_azimuth==90&NS_azimuth==180,90+alpha,
ifelse(EW_azimuth==270&NS_azimuth==0,270+alpha,270-alpha))), type = "angles", units = "degrees", template = "geographics"))))
#is the desired flight azimuth to get home on the shortest linear distance "Distance_to_home"
return(paste("Distance",Distance_to_home,"azimuth",Homing_azimuth)) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
N_Vector_String_Shifted_atan2 <- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_distance<-as.numeric(NCP_altitude_displacement-NCP_altitude_home)*111 #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
Hour_angle_diff<-as.circular( Expected_hour_angle_displacement-Observed_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(Hour_angle_diff*111.32*as.numeric(cos(NCP_altitude_displacement*pi/180)))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-atan2(EW_distance,NS_distance)#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
#Homing_azimuth<-(alpha*180/pi)+180
Homing_azimuth<-((alpha*180/pi) %% 360 + 360)%% 360
return(paste("Distance",Distance_to_home,"azimuth",Homing_azimuth)) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#With time shift - Separate function for distance to home and home azimuth for use is analysis
################################################################################################
#Straight line distance to home function
########################################
N_Vector_Distance_Shifted <- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_distance<-as.numeric(abs(NCP_altitude_displacement-NCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(NCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
return(Distance_to_home)# If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#Straight line azimuth home function
####################################
N_Vector_Azimuth_Shifted <- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_distance<-as.numeric(abs(NCP_altitude_displacement-NCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(NCP_altitude_displacement>NCP_altitude_home,180,0), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(NCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-conversion.circular(as.circular(atan(NS_distance/EW_distance), type = "angles", units = "radians", template = "geographics"), type = "angles", units = "degrees", template = "geographics")#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
#צריך לשנות את הפונקציה שבמקום התנאי הזה יהיה חיבור רכיבים כמו ביו וי של הרוח
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
Homing_azimuth<-ifelse (NS_distance == 0 & EW_distance == 0,"Home",
ifelse(NS_distance == 0, EW_azimuth ,
ifelse (EW_distance == 0 , NS_azimuth,
as.circular(ifelse(EW_azimuth==90&NS_azimuth==0,90-alpha,
ifelse(EW_azimuth==90&NS_azimuth==180,90+alpha,
ifelse(EW_azimuth==270&NS_azimuth==0,270+alpha,270-alpha))), type = "angles", units = "degrees", template = "geographics"))))
#is the desired flight azimuth to get home on the shortest linear distance "Distance_to_home"
return(Homing_azimuth) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
N_Vector_Azimuth_Shifted_atan2 <- function(NCP_altitude_displacement,NCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_distance<-as.numeric(NCP_altitude_displacement-NCP_altitude_home)*111 #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular( Expected_hour_angle_displacement-Observed_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(Hour_angle_diff*111.32*as.numeric(cos(NCP_altitude_displacement*pi/180)))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-atan2(EW_distance,NS_distance)#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
#Homing_azimuth<-(alpha*180/pi)+180
Homing_azimuth<-((alpha*180/pi) %% 360 + 360)%% 360
return(Homing_azimuth) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#Southern Hemisphere
#Full Binary function - No time shift:
########################################
#Function:
S_Binary_No_Shift<- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_correction<-as.circular(ifelse(SCP_altitude_displacement>SCP_altitude_home,0,ifelse(SCP_altitude_displacementExpected_hour_angle_displacement,270,NA)), type = "angles", units = "degrees", template = "geographics")# EW correction, NA marks Obsereved-Expected equivalence, meaning no correction needed
t<-mean.circular(as.circular(na.omit(c(NS_correction,EW_correction)), type = "angles", units = "degrees", template = "geographics"))#na.omit remove NAs from the mean calculation - because they signify ne correction needed on the relevant axis
return(ifelse(all(is.na(t)),"Home",ifelse( t>0,t,360+t))) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#Full Binary function - with time shift
########################################
#Time shift is integrated in the observed hour angle
S_Binary_Shifted <- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_correction<-as.circular(ifelse(SCP_altitude_displacement>SCP_altitude_home,0,ifelse(SCP_altitude_displacementExpected_hour_angle_displacement,270,NA)), type = "angles", units = "degrees", template = "geographics")# EW correction, NA marks Obsereved-Expected equivalence, meaning no correction needed
t<-mean.circular(as.circular(na.omit(c(NS_correction,EW_correction)), type = "angles", units = "degrees", template = "geographics"))#na.omit remove NAs from the mean calculation - because they signify ne correction needed on the relevant axis
return(ifelse(all(is.na(t)),"Home",ifelse( t>0,t,360+t))) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#Separate functions for North-South and East-West components
############################################################
#North-South component
######################
#Time shift is irrelevant for this compoonent
S_Binary_NS <- function(SCP_altitude_displacement,SCP_altitude_home) {
NS_correction<-as.circular(ifelse(SCP_altitude_displacement>SCP_altitude_home,0,ifelse(SCP_altitude_displacementExpected_hour_angle_displacement,270,NA)), type = "angles", units = "degrees", template = "geographics")# EW correction, NA marks Obsereved-Expected equivalence, meaning no correction needed
return(EW_correction)
}
#With time shift
###############
S_Binary_EW_Shifted <- function(Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length)
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
EW_correction<-as.circular(ifelse(Observed_hour_angle_displacementExpected_hour_angle_displacement,270,NA)), type = "angles", units = "degrees", template = "geographics")# EW correction, NA marks Obsereved-Expected equivalence, meaning no correction needed
return(EW_correction)
}
###############################################################
###############################################################
#VECTOR HOMING FUNCTIONS
###############################################################
###############################################################
#No time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
S_Vector_String_No_Shift <- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_distance<-as.numeric(abs(SCP_altitude_displacement-SCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(SCP_altitude_displacement>SCP_altitude_home,0,180), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(SCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-conversion.circular(as.circular(atan(NS_distance/EW_distance), type = "angles", units = "radians", template = "geographics"), type = "angles", units = "degrees", template = "geographics")#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
Homing_azimuth<-ifelse (NS_distance == 0 & EW_distance == 0,"Home",
ifelse(NS_distance == 0, EW_azimuth ,
ifelse (EW_distance == 0 , NS_azimuth,
as.circular(ifelse(EW_azimuth==90&NS_azimuth==0,90-alpha,
ifelse(EW_azimuth==90&NS_azimuth==180,90+alpha,
ifelse(EW_azimuth==270&NS_azimuth==0,270+alpha,270-alpha))), type = "angles", units = "degrees", template = "geographics"))))
#is the desired flight azimuth to get home on the shortest linear distance "Distance_to_home"
return(paste("Distance",Distance_to_home,"azimuth",Homing_azimuth)) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
S_Vector_String_No_Shift_atan2 <- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_distance<-as.numeric(SCP_altitude_displacement-SCP_altitude_home)*111 #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(SCP_altitude_displacement>SCP_altitude_home,0,180), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular( Expected_hour_angle_displacement-Observed_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(Hour_angle_diff*111.32*as.numeric(cos(SCP_altitude_displacement*pi/180)))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-atan2(EW_distance,NS_distance)#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
#Homing_azimuth<-(alpha*180/pi)+180
Homing_azimuth<-((alpha*180/pi) %% 360 + 360)%% 360
return(paste("Distance",Distance_to_home,"azimuth",Homing_azimuth)) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#No time shift - Separate function for distance to home and home azimuth for use is analysis
###########################################################################################
#Straight line distance to home function
#######################################
S_Vector_distance_No_Shift <- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_distance<-as.numeric(abs(SCP_altitude_displacement-SCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(SCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
return(Distance_to_home)# If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#Straight line azimuth home function
###################################
S_Vector_Azimuth_No_Shift <- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_distance<-as.numeric(abs(SCP_altitude_displacement-SCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(SCP_altitude_displacement>SCP_altitude_home,0,180), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(SCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-conversion.circular(as.circular(atan(NS_distance/EW_distance), type = "angles", units = "radians", template = "geographics"), type = "angles", units = "degrees", template = "geographics")#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
Homing_azimuth<-ifelse (NS_distance == 0 & EW_distance == 0,"Home",
ifelse(NS_distance == 0, EW_azimuth ,
ifelse (EW_distance == 0 , NS_azimuth,
as.circular(ifelse(EW_azimuth==90&NS_azimuth==0,90-alpha,
ifelse(EW_azimuth==90&NS_azimuth==180,90+alpha,
ifelse(EW_azimuth==270&NS_azimuth==0,270+alpha,270-alpha))), type = "angles", units = "degrees", template = "geographics"))))
#is the desired flight azimuth to get home on the shortest linear distance "Distance_to_home"
return(Homing_azimuth) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
S_Vector_Azimuth_No_Shift_atan2 <- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement) {
NS_distance<-as.numeric(SCP_altitude_displacement-SCP_altitude_home)*111 #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(SCP_altitude_displacement>SCP_altitude_home,0,180), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular( Expected_hour_angle_displacement-Observed_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(Hour_angle_diff*111.32*as.numeric(cos(SCP_altitude_displacement*pi/180)))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-atan2(EW_distance,NS_distance)#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
#Homing_azimuth<-(alpha*180/pi)+180
Homing_azimuth<-((alpha*180/pi) %% 360 + 360)%% 360
return(Homing_azimuth) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#With time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
S_Vector_String_Shifted<- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_distance<-as.numeric(abs(SCP_altitude_displacement-SCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(SCP_altitude_displacement>SCP_altitude_home,0,180), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(SCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-conversion.circular(as.circular(atan(NS_distance/EW_distance), type = "angles", units = "radians", template = "geographics"), type = "angles", units = "degrees", template = "geographics")#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different calculation for each of the for component direction combinations
Homing_azimuth<-ifelse (NS_distance == 0 & EW_distance == 0,"Home",
ifelse(NS_distance == 0, EW_azimuth ,
ifelse (EW_distance == 0 , NS_azimuth,
as.circular(ifelse(EW_azimuth==90&NS_azimuth==0,90-alpha,
ifelse(EW_azimuth==90&NS_azimuth==180,90+alpha,
ifelse(EW_azimuth==270&NS_azimuth==0,270+alpha,270-alpha))), type = "angles", units = "degrees", template = "geographics"))))
#is the desired flight azimuth to get home on the shortest linear distance "Distance_to_home"
return(paste("Distance",Distance_to_home,"azimuth",Homing_azimuth)) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
S_Vector_String_Shifted_atan2 <- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_distance<-as.numeric(abs(SCP_altitude_displacement-SCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(SCP_altitude_displacement>SCP_altitude_home,0,180), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
Hour_angle_diff<-as.circular( Expected_hour_angle_displacement-Observed_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(Hour_angle_diff*111.32*as.numeric(cos(SCP_altitude_displacement*pi/180)))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-atan2(EW_distance,NS_distance)#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
#Homing_azimuth<-(alpha*180/pi)+180
Homing_azimuth<-((alpha*180/pi) %% 360 + 360)%% 360
return(paste("Distance",Distance_to_home,"azimuth",Homing_azimuth)) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#With time shift - Separate function for distance to home and home azimuth for use is analysis
################################################################################################
#Straight line distance to home function
########################################
S_Vector_Distance_Shifted <- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_distance<-as.numeric(abs(SCP_altitude_displacement-SCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(SCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
return(Distance_to_home)# If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
#Straight line azimuth home function
####################################
S_Vector_Azimuth_Shifted <- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_distance<-as.numeric(abs(SCP_altitude_displacement-SCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(SCP_altitude_displacement>SCP_altitude_home,0,180), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular(Observed_hour_angle_displacement - Expected_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(abs(Hour_angle_diff*111.32*as.numeric(cos(SCP_altitude_displacement*pi/180))))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-conversion.circular(as.circular(atan(NS_distance/EW_distance), type = "angles", units = "radians", template = "geographics"), type = "angles", units = "degrees", template = "geographics")#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
Homing_azimuth<-ifelse (NS_distance == 0 & EW_distance == 0,"Home",
ifelse(NS_distance == 0, EW_azimuth ,
ifelse (EW_distance == 0 , NS_azimuth,
as.circular(ifelse(EW_azimuth==90&NS_azimuth==0,90-alpha,
ifelse(EW_azimuth==90&NS_azimuth==180,90+alpha,
ifelse(EW_azimuth==270&NS_azimuth==0,270+alpha,270-alpha))), type = "angles", units = "degrees", template = "geographics"))))
#is the desired flight azimuth to get home on the shortest linear distance "Distance_to_home"
return(Homing_azimuth) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
S_Vector_Azimuth_Shifted_atan2 <- function(SCP_altitude_displacement,SCP_altitude_home,Time_from_sunrise_at_displacement,Day_length,Observed_hour_angle_displacement_no_shift, Time_shift) {
NS_distance<-as.numeric(abs(SCP_altitude_displacement-SCP_altitude_home)*111) #In km - this is the average width of a latitudinal degree
##The is the north-south component of the home vector
NS_azimuth<-ifelse(NS_distance==0,NA, as.circular(ifelse(SCP_altitude_displacement>SCP_altitude_home,0,180), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of the component - due north (0), or due south (180)
Observed_hour_angle_displacement<-Observed_hour_angle_displacement_no_shift+Time_shift*180/Day_length#There might be a better way to do this becasue the observed that the function inputs is meant to contain the time shift
Expected_hour_angle_displacement<-as.circular(Time_from_sunrise_at_displacement*180/Day_length, type = "angles", units ="degrees", template = "geographics")#Expected hor angle calculation
Hour_angle_diff<-as.circular( Expected_hour_angle_displacement-Observed_hour_angle_displacement, type = "angles", units ="degrees", template = "geographics")
#This angle (assuming there is no time shift) represents displacement distance in degrees on the EW axis
EW_distance<-as.numeric(Hour_angle_diff*111.32*as.numeric(cos(SCP_altitude_displacement*pi/180)))#Output in Km, NCP_altitude_displacement converted to radians (pi/180)
#This is the size of the EW component of the home vector
EW_azimuth<-ifelse(EW_distance==0,NA, as.circular(ifelse(Observed_hour_angle_displacement>Expected_hour_angle_displacement,270,90), type = "angles", units ="degrees", template = "geographics"))
#This is the azimuth of this component-due east (90) or due west (270)
#This doesn't need a condition to account for one or both of the compnents being zero becasue the formula hold - it will give the length of the non-zero
#compnent, or zero if both are zeros
Distance_to_home<-as.numeric(sqrt(EW_distance^2+NS_distance^2))
#The straight line distance to home, obtain using Pithagoras as the Hypotenuse of a right angled triangle with EW distancee
#and NS distance as the two other sides
##Convert chord distance (straight line) to arc distance (real distance across a sphere with the earths' average diameter)
##Calculate the arc angle
##I added the condition here because asin can only take [-1,1], and acsc can take anything but that range. The condition basically says if distance to home is larger than the denominator in the brackets of asin, meaning it is larger then 1, (negative values are impossible), use acsc
Sigma<-ifelse(Distance_to_home<12742,2*asin(Distance_to_home/(2*6371)), 2*acsc(Distance_to_home/(2*6371)))##6371 is the earth's reference radius
##Calculate the arc distance into Distance_to_home
Distance_to_home<-Sigma*6371
##Alpha is the angle between the EW component and the homing vector
alpha<-atan2(EW_distance,NS_distance)#Convert to angle separately
#the angle between the NS distance (which is pointing at azimuth 0) and the Hypotenuse
#To get the Homing azimuth we need a condition set because the calculation varies for the four cases (north+west,north+east,south+west,south+east)
##This conditions outputs the correct azimuth based on alpha and the direction of the North South and East West component. Because azimuth is relative
## To north, to get the right azimuth we need a different caclulation for each of the for component direction combinations
#Homing_azimuth<-(alpha*180/pi)+180
Homing_azimuth<-((alpha*180/pi) %% 360 + 360)%% 360
return(Homing_azimuth) # If both axis get NA, it means you are home, otherwise, it correctes for the negative output automatically produced by mean.circular by adding 360
}
```
Apllying the functions n the same order as they appear in the previous chunck
```{r chunk-name, warning=FALSE, message=FALSE}
###Table100
##Change parameters types
#Table$Latitude_home<-as.circular(Table$Latitude_home, type = "angles", units ="degrees", template = "geographics")
#Table$Latitude_displacement<-as.circular(Table$Latitude_displacement, type = "angles", units ="degrees", template = "geographics")
#Table$Day_length<-as.numeric(Table$Day_length)#in hours
#Table$Time_from_sunrise<-as.numeric(Table$Time_from_sunrise)#in hours
#Table$Observed_hour_angle<-as.circular(Table$Observed_hour_angle, type = "angles", units ="degrees", template = "geographics")
#Table$Observed_hour_angle_no_shift<-as.circular(Table$Observed_hour_angle, type = "angles", units ="degrees", template = "geographics")
#Table$Time_shift<-as.numeric(Table$Time_shift)#in hours
##Sample the data its happenning slow
set.seed(123)
Table2<-Table_100[sample(nrow(Table_100), 100000, replace = FALSE), ]
#Table2<-Table
rm(Table)
##N_Binary_No_Shift####
#######################
N_Binary_No_Shift<-Vectorize(N_Binary_No_Shift)## This steps changes the functions so that they can take vectors (table columns), rather then scalar numbers
Table2$N_Binary_No_Shift<-N_Binary_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
##N_Binary_Shifted##
####################
N_Binary_Shifted<-Vectorize(N_Binary_Shifted)
Table2$N_Binary_Shifted<-N_Binary_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
#Separate functions for North-South and East-West components
############################################################
#North-South component
######################
#Time shift is irrelevant for this compoonent
N_Binary_NS<-Vectorize(N_Binary_NS )
Table2$N_Binary_NS<-N_Binary_NS(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home)
#East-West component
####################
#No time shift
###############
N_Binary_EW_No_Shift<-Vectorize(N_Binary_EW_No_Shift)
Table2$N_Binary_EW_No_Shift<-N_Binary_EW_No_Shift(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle
)
#With time shift
###############
N_Binary_EW_Shifted<-Vectorize(N_Binary_EW_Shifted)
Table2$N_Binary_EW_Shifted<-N_Binary_EW_Shifted(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift
)
###############################################################
###############################################################
#VECTOR HOMING FUNCTIONS
###############################################################
###############################################################
#No time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
N_Vector_String_No_Shift<-Vectorize(N_Vector_String_No_Shift)
Table2$N_Vector_String_No_Shift<-N_Vector_String_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
N_Vector_String_No_Shift_atan2<-Vectorize(N_Vector_String_No_Shift_atan2)
Table2$N_Vector_String_No_Shift_atan2<-N_Vector_String_No_Shift_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#No time shift - Separate function for distance to home and home azimuth for use is analysis
###########################################################################################
#Straight line distance to home function
#######################################
N_Vector_distance_No_Shift<-Vectorize(N_Vector_distance_No_Shift)
Table2$N_Vector_distance_No_Shift<-N_Vector_distance_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#Straight line azimuth home function
###################################
N_Vector_Azimuth_No_Shift<-Vectorize(N_Vector_Azimuth_No_Shift)
Table2$N_Vector_Azimuth_No_Shift<-N_Vector_Azimuth_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
N_Vector_Azimuth_No_Shift_atan2<-Vectorize(N_Vector_Azimuth_No_Shift_atan2)
Table2$N_Vector_Azimuth_No_Shift_atan2<-N_Vector_Azimuth_No_Shift_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#With time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
N_Vector_String_Shifted<-Vectorize(N_Vector_String_Shifted)
Table2$N_Vector_String_Shifted<-N_Vector_String_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
N_Vector_String_Shifted_atan2<-Vectorize(N_Vector_String_Shifted_atan2)
Table2$N_Vector_String_Shifted_atan2<-N_Vector_String_Shifted_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
#With time shift - Separate function for distance to home and home azimuth for use is analysis
################################################################################################
#Straight line distance to home function
########################################
N_Vector_Distance_Shifted<-Vectorize(N_Vector_Distance_Shifted)
Table2$N_Vector_Distance_Shifted<-N_Vector_Distance_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
#Straight line azimuth home function
####################################
N_Vector_Azimuth_Shifted<-Vectorize(N_Vector_Azimuth_Shifted)
Table2$N_Vector_Azimuth_Shifted<-N_Vector_Azimuth_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
N_Vector_Azimuth_Shifted_atan2<-Vectorize(N_Vector_Azimuth_Shifted_atan2)
Table2$N_Vector_Azimuth_Shifted_atan2<-N_Vector_Azimuth_Shifted_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
####Southern function were not yet adressed - The entire comparison df is for northern based on the geosphere function definition. Run the functions and then
###Figure it out
#Southern Hemisphere
#Full Binary function - No time shift:
########################################
S_Binary_No_Shift<-Vectorize(S_Binary_No_Shift)
Table2$S_Binary_No_Shift<-S_Binary_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#Full Binary function - with time shift
########################################
#Time shift is integrated in the observed hour angle
S_Binary_Shifted<-Vectorize(S_Binary_Shifted)
Table2$S_Binary_Shifted<-S_Binary_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
#Separate functions for North-South and East-West components
############################################################
#North-South component
######################
#Time shift is irrelevant for this compoonent
S_Binary_NS<-Vectorize(S_Binary_NS)
Table2$S_Binary_NS<-S_Binary_NS(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home)
#East-West component
####################
#No time shift
###############
S_Binary_EW_No_Shift<-Vectorize(S_Binary_EW_No_Shift)
Table2$S_Binary_EW_No_Shift<-S_Binary_EW_No_Shift(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#With time shift
###############
S_Binary_EW_Shifted<-Vectorize(S_Binary_EW_Shifted)
Table2$S_Binary_EW_Shifted<-S_Binary_EW_Shifted(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
###############################################################
###############################################################
#VECTOR HOMING FUNCTIONS
###############################################################
###############################################################
#No time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
S_Vector_String_No_Shift<-Vectorize(S_Vector_String_No_Shift)
Table2$S_Vector_String_No_Shift<-S_Vector_String_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
S_Vector_String_No_Shift_atan2<-Vectorize(S_Vector_String_No_Shift_atan2)
Table2$S_Vector_String_No_Shift_atan2<-S_Vector_String_No_Shift_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#No time shift - Separate function for distance to home and home azimuth for use is analysis
###########################################################################################
#Straight line distance to home function
#######################################
S_Vector_distance_No_Shift<-Vectorize(S_Vector_distance_No_Shift)
Table2$S_Vector_distance_No_Shift<-S_Vector_distance_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#Straight line azimuth home function
###################################
S_Vector_Azimuth_No_Shift<-Vectorize(S_Vector_Azimuth_No_Shift)
Table2$S_Vector_Azimuth_No_Shift<-S_Vector_Azimuth_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
S_Vector_Azimuth_No_Shift_atan2<-Vectorize(S_Vector_Azimuth_No_Shift_atan2)
Table2$S_Vector_Azimuth_No_Shift_atan2<-S_Vector_Azimuth_No_Shift_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#With time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
S_Vector_String_Shifted<-Vectorize(S_Vector_String_Shifted)
Table2$S_Vector_String_Shifted<-S_Vector_String_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
S_Vector_String_Shifted_atan2<-Vectorize(S_Vector_String_Shifted_atan2)
Table2$S_Vector_String_Shifted_atan2<-S_Vector_String_Shifted_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
#With time shift - Separate function for distance to home and home azimuth for use is analysis
################################################################################################
#Straight line distance to home function
########################################
S_Vector_Distance_Shifted<-Vectorize(S_Vector_Distance_Shifted)
Table2$S_Vector_Distance_Shifted<-S_Vector_Distance_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
#Straight line azimuth home function
####################################
S_Vector_Azimuth_Shifted<-Vectorize(S_Vector_Azimuth_Shifted)
Table2$S_Vector_Azimuth_Shifted<-S_Vector_Azimuth_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
S_Vector_Azimuth_Shifted_atan2<-Vectorize(S_Vector_Azimuth_Shifted_atan2)
Table2$S_Vector_Azimuth_Shifted_atan2<-S_Vector_Azimuth_Shifted_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
Table_100<-Table2
set.seed(123)
Table2<-Table_1000[sample(nrow(Table_1000), 100000, replace = FALSE), ]
##N_Binary_No_Shift####
#######################
N_Binary_No_Shift<-Vectorize(N_Binary_No_Shift)## This steps changes the functions so that they can take vectors (table columns), rather then scalar numbers
Table2$N_Binary_No_Shift<-N_Binary_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
##N_Binary_Shifted##
####################
N_Binary_Shifted<-Vectorize(N_Binary_Shifted)
Table2$N_Binary_Shifted<-N_Binary_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
#Separate functions for North-South and East-West components
############################################################
#North-South component
######################
#Time shift is irrelevant for this compoonent
N_Binary_NS<-Vectorize(N_Binary_NS )
Table2$N_Binary_NS<-N_Binary_NS(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home)
#East-West component
####################
#No time shift
###############
N_Binary_EW_No_Shift<-Vectorize(N_Binary_EW_No_Shift)
Table2$N_Binary_EW_No_Shift<-N_Binary_EW_No_Shift(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle
)
#With time shift
###############
N_Binary_EW_Shifted<-Vectorize(N_Binary_EW_Shifted)
Table2$N_Binary_EW_Shifted<-N_Binary_EW_Shifted(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift
)
###############################################################
###############################################################
#VECTOR HOMING FUNCTIONS
###############################################################
###############################################################
#No time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
N_Vector_String_No_Shift<-Vectorize(N_Vector_String_No_Shift)
Table2$N_Vector_String_No_Shift<-N_Vector_String_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
N_Vector_String_No_Shift_atan2<-Vectorize(N_Vector_String_No_Shift_atan2)
Table2$N_Vector_String_No_Shift_atan2<-N_Vector_String_No_Shift_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#No time shift - Separate function for distance to home and home azimuth for use is analysis
###########################################################################################
#Straight line distance to home function
#######################################
N_Vector_distance_No_Shift<-Vectorize(N_Vector_distance_No_Shift)
Table2$N_Vector_distance_No_Shift<-N_Vector_distance_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#Straight line azimuth home function
###################################
N_Vector_Azimuth_No_Shift<-Vectorize(N_Vector_Azimuth_No_Shift)
Table2$N_Vector_Azimuth_No_Shift<-N_Vector_Azimuth_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
N_Vector_Azimuth_No_Shift_atan2<-Vectorize(N_Vector_Azimuth_No_Shift_atan2)
Table2$N_Vector_Azimuth_No_Shift_atan2<-N_Vector_Azimuth_No_Shift_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#With time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
N_Vector_String_Shifted<-Vectorize(N_Vector_String_Shifted)
Table2$N_Vector_String_Shifted<-N_Vector_String_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
N_Vector_String_Shifted_atan2<-Vectorize(N_Vector_String_Shifted_atan2)
Table2$N_Vector_String_Shifted_atan2<-N_Vector_String_Shifted_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
#With time shift - Separate function for distance to home and home azimuth for use is analysis
################################################################################################
#Straight line distance to home function
########################################
N_Vector_Distance_Shifted<-Vectorize(N_Vector_Distance_Shifted)
Table2$N_Vector_Distance_Shifted<-N_Vector_Distance_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
#Straight line azimuth home function
####################################
N_Vector_Azimuth_Shifted<-Vectorize(N_Vector_Azimuth_Shifted)
Table2$N_Vector_Azimuth_Shifted<-N_Vector_Azimuth_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
N_Vector_Azimuth_Shifted_atan2<-Vectorize(N_Vector_Azimuth_Shifted_atan2)
Table2$N_Vector_Azimuth_Shifted_atan2<-N_Vector_Azimuth_Shifted_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
####Southern function were not yet adressed - The entire comparison df is for northern based on the geosphere function definition. Run the functions and then
###Figure it out
#Southern Hemisphere
#Full Binary function - No time shift:
########################################
S_Binary_No_Shift<-Vectorize(S_Binary_No_Shift)
Table2$S_Binary_No_Shift<-S_Binary_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#Full Binary function - with time shift
########################################
#Time shift is integrated in the observed hour angle
S_Binary_Shifted<-Vectorize(S_Binary_Shifted)
Table2$S_Binary_Shifted<-S_Binary_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
#Separate functions for North-South and East-West components
############################################################
#North-South component
######################
#Time shift is irrelevant for this compoonent
S_Binary_NS<-Vectorize(S_Binary_NS)
Table2$S_Binary_NS<-S_Binary_NS(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home)
#East-West component
####################
#No time shift
###############
S_Binary_EW_No_Shift<-Vectorize(S_Binary_EW_No_Shift)
Table2$S_Binary_EW_No_Shift<-S_Binary_EW_No_Shift(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#With time shift
###############
S_Binary_EW_Shifted<-Vectorize(S_Binary_EW_Shifted)
Table2$S_Binary_EW_Shifted<-S_Binary_EW_Shifted(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
###############################################################
###############################################################
#VECTOR HOMING FUNCTIONS
###############################################################
###############################################################
#No time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
S_Vector_String_No_Shift<-Vectorize(S_Vector_String_No_Shift)
Table2$S_Vector_String_No_Shift<-S_Vector_String_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
S_Vector_String_No_Shift_atan2<-Vectorize(S_Vector_String_No_Shift_atan2)
Table2$S_Vector_String_No_Shift_atan2<-S_Vector_String_No_Shift_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#No time shift - Separate function for distance to home and home azimuth for use is analysis
###########################################################################################
#Straight line distance to home function
#######################################
S_Vector_distance_No_Shift<-Vectorize(S_Vector_distance_No_Shift)
Table2$S_Vector_distance_No_Shift<-S_Vector_distance_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#Straight line azimuth home function
###################################
S_Vector_Azimuth_No_Shift<-Vectorize(S_Vector_Azimuth_No_Shift)
Table2$S_Vector_Azimuth_No_Shift<-S_Vector_Azimuth_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
S_Vector_Azimuth_No_Shift_atan2<-Vectorize(S_Vector_Azimuth_No_Shift_atan2)
Table2$S_Vector_Azimuth_No_Shift_atan2<-S_Vector_Azimuth_No_Shift_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#With time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
S_Vector_String_Shifted<-Vectorize(S_Vector_String_Shifted)
Table2$S_Vector_String_Shifted<-S_Vector_String_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
S_Vector_String_Shifted_atan2<-Vectorize(S_Vector_String_Shifted_atan2)
Table2$S_Vector_String_Shifted_atan2<-S_Vector_String_Shifted_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
#With time shift - Separate function for distance to home and home azimuth for use is analysis
################################################################################################
#Straight line distance to home function
########################################
S_Vector_Distance_Shifted<-Vectorize(S_Vector_Distance_Shifted)
Table2$S_Vector_Distance_Shifted<-S_Vector_Distance_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
#Straight line azimuth home function
####################################
S_Vector_Azimuth_Shifted<-Vectorize(S_Vector_Azimuth_Shifted)
Table2$S_Vector_Azimuth_Shifted<-S_Vector_Azimuth_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
S_Vector_Azimuth_Shifted_atan2<-Vectorize(S_Vector_Azimuth_Shifted_atan2)
Table2$S_Vector_Azimuth_Shifted_atan2<-S_Vector_Azimuth_Shifted_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
Table_1000<-Table2
set.seed(123)
Table2<-Table_20000[sample(nrow(Table_20000), 100000, replace = FALSE), ]
##N_Binary_No_Shift####
#######################
N_Binary_No_Shift<-Vectorize(N_Binary_No_Shift)## This steps changes the functions so that they can take vectors (table columns), rather then scalar numbers
Table2$N_Binary_No_Shift<-N_Binary_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
##N_Binary_Shifted##
####################
N_Binary_Shifted<-Vectorize(N_Binary_Shifted)
Table2$N_Binary_Shifted<-N_Binary_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
#Separate functions for North-South and East-West components
############################################################
#North-South component
######################
#Time shift is irrelevant for this compoonent
N_Binary_NS<-Vectorize(N_Binary_NS )
Table2$N_Binary_NS<-N_Binary_NS(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home)
#East-West component
####################
#No time shift
###############
N_Binary_EW_No_Shift<-Vectorize(N_Binary_EW_No_Shift)
Table2$N_Binary_EW_No_Shift<-N_Binary_EW_No_Shift(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle
)
#With time shift
###############
N_Binary_EW_Shifted<-Vectorize(N_Binary_EW_Shifted)
Table2$N_Binary_EW_Shifted<-N_Binary_EW_Shifted(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift
)
###############################################################
###############################################################
#VECTOR HOMING FUNCTIONS
###############################################################
###############################################################
#No time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
N_Vector_String_No_Shift<-Vectorize(N_Vector_String_No_Shift)
Table2$N_Vector_String_No_Shift<-N_Vector_String_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
N_Vector_String_No_Shift_atan2<-Vectorize(N_Vector_String_No_Shift_atan2)
Table2$N_Vector_String_No_Shift_atan2<-N_Vector_String_No_Shift_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#No time shift - Separate function for distance to home and home azimuth for use is analysis
###########################################################################################
#Straight line distance to home function
#######################################
N_Vector_distance_No_Shift<-Vectorize(N_Vector_distance_No_Shift)
Table2$N_Vector_distance_No_Shift<-N_Vector_distance_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#Straight line azimuth home function
###################################
N_Vector_Azimuth_No_Shift<-Vectorize(N_Vector_Azimuth_No_Shift)
Table2$N_Vector_Azimuth_No_Shift<-N_Vector_Azimuth_No_Shift(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
N_Vector_Azimuth_No_Shift_atan2<-Vectorize(N_Vector_Azimuth_No_Shift_atan2)
Table2$N_Vector_Azimuth_No_Shift_atan2<-N_Vector_Azimuth_No_Shift_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#With time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
N_Vector_String_Shifted<-Vectorize(N_Vector_String_Shifted)
Table2$N_Vector_String_Shifted<-N_Vector_String_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
N_Vector_String_Shifted_atan2<-Vectorize(N_Vector_String_Shifted_atan2)
Table2$N_Vector_String_Shifted_atan2<-N_Vector_String_Shifted_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
#With time shift - Separate function for distance to home and home azimuth for use is analysis
################################################################################################
#Straight line distance to home function
########################################
N_Vector_Distance_Shifted<-Vectorize(N_Vector_Distance_Shifted)
Table2$N_Vector_Distance_Shifted<-N_Vector_Distance_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
#Straight line azimuth home function
####################################
N_Vector_Azimuth_Shifted<-Vectorize(N_Vector_Azimuth_Shifted)
Table2$N_Vector_Azimuth_Shifted<-N_Vector_Azimuth_Shifted(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
N_Vector_Azimuth_Shifted_atan2<-Vectorize(N_Vector_Azimuth_Shifted_atan2)
Table2$N_Vector_Azimuth_Shifted_atan2<-N_Vector_Azimuth_Shifted_atan2(NCP_altitude_displacement = Table2$Latitude_displacement,
NCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement_no_shift = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift )
####Southern function were not yet adressed - The entire comparison df is for northern based on the geosphere function definition. Run the functions and then
###Figure it out
#Southern Hemisphere
#Full Binary function - No time shift:
########################################
S_Binary_No_Shift<-Vectorize(S_Binary_No_Shift)
Table2$S_Binary_No_Shift<-S_Binary_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#Full Binary function - with time shift
########################################
#Time shift is integrated in the observed hour angle
S_Binary_Shifted<-Vectorize(S_Binary_Shifted)
Table2$S_Binary_Shifted<-S_Binary_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
#Separate functions for North-South and East-West components
############################################################
#North-South component
######################
#Time shift is irrelevant for this compoonent
S_Binary_NS<-Vectorize(S_Binary_NS)
Table2$S_Binary_NS<-S_Binary_NS(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home)
#East-West component
####################
#No time shift
###############
S_Binary_EW_No_Shift<-Vectorize(S_Binary_EW_No_Shift)
Table2$S_Binary_EW_No_Shift<-S_Binary_EW_No_Shift(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#With time shift
###############
S_Binary_EW_Shifted<-Vectorize(S_Binary_EW_Shifted)
Table2$S_Binary_EW_Shifted<-S_Binary_EW_Shifted(Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
###############################################################
###############################################################
#VECTOR HOMING FUNCTIONS
###############################################################
###############################################################
#No time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
S_Vector_String_No_Shift<-Vectorize(S_Vector_String_No_Shift)
Table2$S_Vector_String_No_Shift<-S_Vector_String_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
S_Vector_String_No_Shift_atan2<-Vectorize(S_Vector_String_No_Shift_atan2)
Table2$S_Vector_String_No_Shift_atan2<-S_Vector_String_No_Shift_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#No time shift - Separate function for distance to home and home azimuth for use is analysis
###########################################################################################
#Straight line distance to home function
#######################################
S_Vector_distance_No_Shift<-Vectorize(S_Vector_distance_No_Shift)
Table2$S_Vector_distance_No_Shift<-S_Vector_distance_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#Straight line azimuth home function
###################################
S_Vector_Azimuth_No_Shift<-Vectorize(S_Vector_Azimuth_No_Shift)
Table2$S_Vector_Azimuth_No_Shift<-S_Vector_Azimuth_No_Shift(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
S_Vector_Azimuth_No_Shift_atan2<-Vectorize(S_Vector_Azimuth_No_Shift_atan2)
Table2$S_Vector_Azimuth_No_Shift_atan2<-S_Vector_Azimuth_No_Shift_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle)
#With time shift
#############
#String function
###############
#Returns string: "Distance ------, Azimuth-------" For use in testing and isolated cases
S_Vector_String_Shifted<-Vectorize(S_Vector_String_Shifted)
Table2$S_Vector_String_Shifted<-S_Vector_String_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
S_Vector_String_Shifted_atan2<-Vectorize(S_Vector_String_Shifted_atan2)
Table2$S_Vector_String_Shifted_atan2<-S_Vector_String_Shifted_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
#With time shift - Separate function for distance to home and home azimuth for use is analysis
################################################################################################
#Straight line distance to home function
########################################
S_Vector_Distance_Shifted<-Vectorize(S_Vector_Distance_Shifted)
Table2$S_Vector_Distance_Shifted<-S_Vector_Distance_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
#Straight line azimuth home function
####################################
S_Vector_Azimuth_Shifted<-Vectorize(S_Vector_Azimuth_Shifted)
Table2$S_Vector_Azimuth_Shifted<-S_Vector_Azimuth_Shifted(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
S_Vector_Azimuth_Shifted_atan2<-Vectorize(S_Vector_Azimuth_Shifted_atan2)
Table2$S_Vector_Azimuth_Shifted_atan2<-S_Vector_Azimuth_Shifted_atan2(SCP_altitude_displacement = Table2$Latitude_displacement,
SCP_altitude_home = Table2$Latitude_home,
Time_from_sunrise_at_displacement = Table2$Time_from_sunrise,
Day_length = Table2$Day_length,
Observed_hour_angle_displacement = Table2$Observed_hour_angle,
Time_shift = Table2$Time_shift)
Table_20000<-Table2
#save(Table2,file="Test_data_V1_lat0_90_lon0_180_shift_0_6")
Table2<-rbind(Table_100,Table_1000,Table_20000)
save(Table2,file="Simulation_data_V9_shift_min6_6_by_0.5")
```
Analisys and presentation
Figure 3
```{r}
load("Supplamentary_data")
#Northern Hemisphere
Table2$N_Binary_No_Shift<-as.circular(Table2$N_Binary_No_Shift, type = "angles", units ="degrees", template = "geographics")
Table2$Azimuth_rhumb_geo<-as.circular(Table2$Azimuth_rhumb_geo, type = "angles", units ="degrees", template = "geographics")
Table2$angular_diff<-Table2$N_Binary_No_Shift-Table2$Azimuth_rhumb_geo
Table2$angular_diff<-as.numeric(Table2$angular_diff)
Table2$abs_angular_diff<-abs(Table2$angular_diff)
Table2$N_Binary_No_Shift<-as.numeric(Table2$N_Binary_No_Shift)
Table2$Azimuth_rhumb_geo<-as.numeric(Table2$Azimuth_rhumb_geo)
Table2$abs_angular_diff<-as.numeric(Table2$abs_angular_diff)
Table2$angular_diff<-as.numeric(Table2$angular_diff)
Table2$abs_angular_diff<-as.numeric(abs(Table2$angular_diff))
Table2$angular_diff<-ifelse(Table2$angular_diff>359,0,Table2$angular_diff)#These mean 0 difference
Table2$angular_diff<-ifelse(Table2$angular_diff>179,0,Table2$angular_diff)#single one, milimeters apart
t<-Table2%>%filter(angular_diff>170)
#Mechanism output vs real distance
Hundred<-Table2%>%filter(range==100)
range(Hundred$angular_diff)
sum(Hundred$angular_diff>170)
#100km
Hundreds_error_distribution_azimuth_N<-ggplot(Hundred, aes(x = angular_diff)) +
geom_histogram(aes(y = after_stat(count / sum(count))),fill="#7aa0c0",colour = "black",size = 0.01) +
scale_y_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "> 0 km\n< 100 km")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
range(Hundred$angular_diff)
sum(Hundred$angular_diff>50)
##Use thousand circle only - 100, 20,000 are identical, will be reported verbally
#1000km
Thousand<-Table2%>%filter(range==1000)##Maybe increase sample size
Thousand_error_distribution_azimuth_N<-ggplot(Thousand, aes(x = angular_diff)) +
geom_histogram(aes(y = after_stat(count / sum(count))),fill="#7aa0c0",colour = "black") +
scale_y_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "> 100 km\n< 1,000 km")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
Thousand_plot_azimuth_N<-ggplot(Thousand,aes(x = Azimuth_rhumb_geo, y = N_Binary_No_Shift)) +
geom_point(aes(color=abs_angular_diff),size=1) +
geom_smooth(method = "lm", col = "blue") + # Adds linear regression line
labs(x = "Angle = Rhumb azimuth (deg)",
y = "Radial distance = Mechanism output (deg)")+
theme_minimal()+coord_polar()+scale_y_continuous(expand = (0),breaks = c(0, 45, 90,135,180,224,270,315,360),limits = c(0, 360))+theme(legend.position = "bottom")+
scale_color_continuous(
name = "Error\nsize (°)", # Set the legend title
guide = guide_colorbar(
barwidth = unit(0.2, "cm"),
barheight = unit(2, "cm")
))+
theme(
legend.position = "right" # Aligns the legend to the right edge
)+scale_x_continuous(breaks = c(0, 45, 90,135,180,224,270,315,360)) +
expand_limits(x = 0)
#10000km
Ten_thousand<-Table2%>%filter(range==20000)
Ten_thousand_error_distribution_azimuth_N<-ggplot(Ten_thousand, aes(x = angular_diff)) +
geom_histogram(aes(y = after_stat(count / sum(count))),fill="#7aa0c0",colour = "black") +
scale_y_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "> 1,000 km\n< 20,000 km")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
model_1000<-lm(Thousand$N_Binary_No_Shift~Thousand$Azimuth_rhumb_geo)
summary(model_1000)
model_100<-lm(Hundred$N_Binary_No_Shift~Hundred$Azimuth_rhumb_geo)
summary(model_100)
model_10000<-lm(Ten_thousand$N_Binary_No_Shift~Ten_thousand$Azimuth_rhumb_geo)
summary(model_10000)
###Southern Hemisphere
Table2$S_Binary_No_Shift<-as.circular(Table2$S_Binary_No_Shift, type = "angles", units ="degrees", template = "geographics")
Table2$Azimuth_rhumb_geo<-as.circular(Table2$Azimuth_rhumb_geo, type = "angles", units ="degrees", template = "geographics")
Table2$angular_diff<-Table2$S_Binary_No_Shift-Table2$Azimuth_rhumb_geo_S
Table2$angular_diff<-as.numeric(Table2$angular_diff)
Table2$abs_angular_diff<-abs(Table2$angular_diff)
Table2$S_Binary_No_Shift<-as.numeric(Table2$S_Binary_No_Shift)
Table2$Azimuth_rhumb_geo<-as.numeric(Table2$Azimuth_rhumb_geo)
Table2$abs_angular_diff<-as.numeric(Table2$abs_angular_diff)
Table2$angular_diff<-as.numeric(Table2$angular_diff)
Table2$angular_diff<-ifelse(Table2$angular_diff>359,0,Table2$angular_diff)#These mean 0 difference
Table2$angular_diff<-ifelse(Table2$angular_diff>179,0,Table2$angular_diff)#single one, milimeters apart
Table2$abs_angular_diff<-as.numeric(abs(Table2$angular_diff))
range(Table2$angular_diff)
#Mechanism output vs real distance
Hundred<-Table2%>%filter(range==100)
#100km
Hundreds_error_distribution_azimuth_S<-ggplot(Hundred, aes(x = angular_diff)) +
geom_histogram(aes(y = after_stat(count / sum(count))),fill="#7aa0c0",colour = "black",size = 0.01) +
scale_y_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "> 0 km\n< 100 km")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
##Use thousand circle only - 100, 20,000 are identical, will be reported verbally
#1000km
Thousand<-Table2%>%filter(range==1000)##Maybe increase sample size
Thousand_error_distribution_azimuth_S<-ggplot(Thousand, aes(x = angular_diff)) +
geom_histogram(aes(y = after_stat(count / sum(count))),fill="#7aa0c0",colour = "black") +
scale_y_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "> 100 km\n< 1,000 km")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
Thousand_plot_azimuth_S<-ggplot(Thousand,aes(x = Azimuth_rhumb_geo_S, y = S_Binary_No_Shift)) +
geom_point(aes(color=abs_angular_diff),size=1) +
geom_smooth(method = "lm", col = "blue") + # Adds linear regression line
labs(x = "Angle = Rhumb azimuth (deg)",
y = "Radial distance = Mechanism output (deg)")+scale_y_continuous(expand = (0),breaks = c(0, 45, 90,135,180,224,270,315,360),limits = c(0, 360))+
theme_minimal()+coord_polar()+theme(legend.position = "bottom")+
scale_color_continuous(
name = "Error\nsize (°)", # Set the legend title
guide = guide_colorbar(
barwidth = unit(0.2, "cm"),
barheight = unit(2, "cm")
))+
theme(
legend.position = "right" # Aligns the legend to the right edge
)+scale_x_continuous(breaks = c(0, 45, 90,135,180,224,270,315,360))
#10000km
Ten_thousand<-Table2%>%filter(range==20000)
Ten_thousand_error_distribution_azimuth_S<-ggplot(Ten_thousand, aes(x = angular_diff)) +
geom_histogram(aes(y = after_stat(count / sum(count))),fill="#7aa0c0",colour = "black") +
scale_y_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "> 1,000 km\n< 20,000 km")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
model_100<-lm(Hundred$S_Binary_No_Shift~Hundred$Azimuth_rhumb_geo_S)
summary(model_100)
model_1000<-lm(Thousand$S_Binary_No_Shift~Thousand$Azimuth_rhumb_geo_S)
summary(model_1000)
model_10000<-lm(Ten_thousand$S_Binary_No_Shift~Ten_thousand$Azimuth_rhumb_geo_S)
summary(model_10000)
Binary_mechanism_summary<-ggdraw() +
theme(plot.background = element_rect(fill="white", color = NA))+
draw_label("Northern Hemisphere", x = 0.5, y = 0.98, size = 18, fontface = "bold") +
draw_plot(Thousand_plot_azimuth_N, x = 0., y = 0.45, width =0.6 , height = .6) +
draw_plot(Hundreds_error_distribution_azimuth_N , x = 0.55, y = 0.5, width =0.15 , height = .2) +
draw_plot(Thousand_error_distribution_azimuth_N, x = 0.70, y = 0.5, width =0.15 , height = .2) +
draw_plot(Ten_thousand_error_distribution_azimuth_N, x = 0.85, y = 0.5, width =0.15 , height = .2) +
draw_line(x = c(0, 1), y = c(.5, .5), color = "black",size = 0.5)+
draw_label("Regression equations: \nMechanism output ~ Homing azimuth", x = 0.78, y = 0.94, size = 12, fontface = "bold")+
draw_line(x = c(0.59, .97), y = c(.915, .915), color = "black",size = 0.5)+
draw_label("Homing Distance < 100km ", x = 0.78, y = 0.9, size = 12,fontface = "bold")+
draw_label(expression(paste("y = 11.23 + 0.93x , p<0.0001, R"^2,"=0.94 ")), x = 0.79, y = 0.878, size = 12)+
draw_label("100km < Homing Distance < 1,000km ", x = 0.79, y = 0.845, size = 12,fontface = "bold")+
draw_label(expression(paste("y = 11.15 + 0.93x , p<0.0001, R"^2,"=0.94 ")), x = 0.79, y = 0.82, size = 12)+
draw_label("1,000km < Homing Distance < 20,000km ", x = 0.79, y = 0.79, size = 12,fontface = "bold")+
draw_label(expression(paste("y = 9.95 + 0.95x , p<0.0001, R"^2,"=0.89 ")), x = 0.79, y = 0.765, size = 12)+
draw_label("Azimuth Error Distributions (deg)", x = 0.78, y = 0.72, size = 12, fontface = "bold") +
draw_line(x = c(0.61, .95), y = c(.705, .705), color = "black",size = 0.5)+
draw_label("Southern Hemisphere", x = 0.5, y = 0.48, size = 18, fontface = "bold") +
draw_plot(Thousand_plot_azimuth_S, x = 0., y = -0.05, width =0.6 , height = .6) +
draw_plot(Hundreds_error_distribution_azimuth_S , x = 0.55, y = 0., width =0.15 , height = .2) +
draw_plot(Thousand_error_distribution_azimuth_S, x = 0.70, y = 0., width =0.15 , height = .2) +
draw_plot(Ten_thousand_error_distribution_azimuth_S, x = 0.85, y = 0, width =0.15 , height = .2) +
draw_label("Regression equations: \nMechanism output ~ Homing azimuth", x = 0.78, y = 0.44, size = 12, fontface = "bold")+
draw_line(x = c(0.59, .97), y = c(.415, .415), color = "black",size = 0.5)+
draw_label("Homing Distance < 100km ", x = 0.78, y = 0.4, size = 12,fontface = "bold")+
draw_label(expression(paste("y = 11.5 + 0.93x , p<0.0001, R"^2,"=0.93 ")), x = 0.79, y = 0.378, size = 12)+
draw_label("100km < Homing Distance < 1,000km ", x = 0.79, y = 0.345, size = 12,fontface = "bold")+
draw_label(expression(paste("y = 11.92 + 0.98x , p<0.0001, R"^2,"=0.94 ")), x = 0.79, y = 0.32, size = 12)+
draw_label("1,000km < Homing Distance < 20,000km ", x = 0.79, y = 0.29, size = 12,fontface = "bold")+
draw_label(expression(paste("y = 16.3 + 0.91x , p<0.0001, R"^2,"=0.96 ")), x = 0.79, y = 0.265, size = 12)+
draw_label("Azimuth Error Distributions (deg)", x = 0.78, y = 0.22, size = 12, fontface = "bold") +
draw_line(x = c(0.61, .95), y = c(.205, .205), color = "black",size = 0.5)+
draw_label(" A.", x = 0.01, y = 0.98, size = 12, fontface = "bold")+
draw_label(" B.", x = 0.01, y = 0.48, size = 12, fontface = "bold")
ggsave("Binary_no_shift_summary.3.png", width =8 , height =9,dpi=300)
ggplot(Hundred, aes(x = Longitude_home, y = angular_diff)) +
geom_point(size=0.1,aes()) +
geom_smooth(method = "lm", col = "blue") + # Adds linear regression line
labs( )+scale_y_continuous(expand = (0))+
stat_regline_equation(label.y = 100, aes(label = paste(..eq.label.., sep = "~~~~"))) +
stat_regline_equation(label.y = 95, aes(label = paste(..rr.label.., sep = "~~~~"))) +
theme_minimal()+
scale_color_continuous(
name = "Error\nsize (%)", # Set the legend title
labels = scales::percent,# Format labels as percentages
guide = guide_colorbar(
barwidth = unit(0.2, "cm"),
barheight = unit(2, "cm")))
```
Figure 4
Vector test
```{r}
load("Supplamentary_data")
#load("Simulation_data_V9.1_Time_shift_with_decimal_corrected")
#plots:
#Mechanism output vs real distance
Table2$Distance_diff<-Table2$N_Vector_distance_No_Shift-Table2$distance_km_geo
hist(Table2$Distance_diff)
#Looks like our function estiamte has more larger then shorter distances compared - maybe because its the geosphere outputs shortest difference and we scalculate fixed azimuth. Test geosphere's rhumb distance as well
##Calculate the relative size of the error - relative to the geosphere output of shortest distance
Table2$Distance_diff_rel<-Table2$Distance_diff/Table2$distance_km_geo
Table2$Distance_diff_rel_abs<-abs(Table2$Distance_diff/Table2$distance_km_geo)
Table2$range<-factor(Table2$range)
#100km
Hundred<-Table2%>%filter(range==100)
Hundreds_error_distribution_distance<-ggplot(Hundred, aes(x = Distance_diff_rel)) +
geom_histogram(aes(y = after_stat(count / sum(count)))) +
scale_y_continuous(labels = scales::percent) +
scale_x_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "Error\ndistribution")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
Hundred_plot_distance<-ggplot(Hundred, aes(x = distance_km_rhumb_geo, y = N_Vector_distance_No_Shift)) +
geom_point(size=0.1,aes(color=Distance_diff_rel_abs)) +
geom_smooth(method = "lm", col = "blue") + # Adds linear regression line
labs( x = "Rhumb distance (km)",
y = "Mechanism output (km)")+scale_y_continuous(expand = (0))+
stat_regline_equation(label.y = 100, aes(label = paste(..eq.label.., sep = "~~~~"))) +
stat_regline_equation(label.y = 95, aes(label = paste(..rr.label.., sep = "~~~~"))) +
theme_minimal()+
scale_color_continuous(
name = "Error\nsize (%)", # Set the legend title
labels = scales::percent,# Format labels as percentages
guide = guide_colorbar(
barwidth = unit(0.2, "cm"),
barheight = unit(2, "cm")
),
breaks = seq(0, 0.25, by = 0.05))+
theme(
legend.position = "right", # Places the legend above the plot
legend.justification = "top",
legend.title = element_text(hjust = 0.5)# Aligns the legend to the right edge
)
Combined_hundered_distance<-ggdraw() +
theme(plot.background = element_rect(fill="white", color = NA))+
draw_plot(Hundred_plot_distance, x = 0, y = 0.0, width =1 , height = 1) +
draw_plot(Hundreds_error_distribution_distance, x = 0.8, y = 0.08, width =.2 , height = 0.5)
#1000km
Thousand<-Table2%>%filter(range==1000)##Maybe increase sample size
Thousands_error_distribution_distance<-ggplot(Thousand, aes(x = Distance_diff_rel)) +
geom_histogram(aes(y = after_stat(count / sum(count)))) +
scale_x_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "Error\ndistribution")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
Thousand_plot_distance<-ggplot(Thousand, aes(x = distance_km_rhumb_geo, y = N_Vector_distance_No_Shift)) +
geom_point(size=0.1,aes(color=Distance_diff_rel)) +
geom_smooth(method = "lm", col = "blue") + # Adds linear regression line
labs(y = "Mechanism output (km)",
x = "Rhumb distance (km)")+scale_y_continuous(expand = (0))+
stat_regline_equation(label.y = 2000, aes(label = paste(..eq.label.., sep = "~~~~"))) +
stat_regline_equation(label.y = 1900, aes(label = paste(..rr.label.., sep = "~~~~"))) +
theme_minimal()+
scale_color_continuous(
name = "Error\nsize (%)", # Set the legend title
labels = scales::percent, # Format labels as percentages
guide = guide_colorbar(
barwidth = unit(0.2, "cm"),
barheight = unit(2, "cm")),
breaks = seq(0, 1, by = 0.2)
)+
theme(
legend.position = "right", # Places the legend above the plot
legend.justification = "top",
legend.title = element_text(hjust = 0.5)# Aligns the legend to the right edge
)
Combined_Thousand_distance<-ggdraw() +
theme(plot.background = element_rect(fill="white", color = NA))+
draw_plot(Thousand_plot_distance, x = 0, y = 0.0, width =1 , height = 1) +
draw_plot(Thousands_error_distribution_distance, x = 0.8, y = 0.08, width =.2 , height = 0.5)
#10000km
Ten_thousand<-Table2%>%filter(range==20000)
Ten_thousands_error_distribution_distance<-ggplot(Ten_thousand, aes(x = Distance_diff_rel)) +
geom_histogram(aes(y = after_stat(count / sum(count)))) +
scale_x_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "Error\ndistribution")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
hist(Ten_thousand$Distance_diff_rel)
Ten_thousand_plot_distance<-ggplot(Ten_thousand, aes(x = distance_km_rhumb_geo, y = N_Vector_distance_No_Shift)) +
geom_point(size=0.1,aes(color=Distance_diff_rel)) +
geom_smooth(method = "lm", col = "blue") + # Adds linear regression line
labs( x = "Rhumb distance (km)",
y = "Mechanism output (km)")+scale_y_continuous(expand = (0))+
stat_regline_equation(label.y = 20000,label.x = 100, aes(label = paste(..eq.label.., sep = "~~~~"))) +
stat_regline_equation(label.y = 19000,label.x = 100, aes(label = paste(..rr.label.., sep = "~~~~"))) +
theme_minimal()+
scale_color_continuous(
name = "Error\nsize (%)", # Set the legend title
labels = scales::percent, # Format labels as percentages
guide = guide_colorbar(
barwidth = unit(0.2, "cm"),
barheight = unit(2, "cm")
))+
theme(
legend.position = "right", # Places the legend above the plot
legend.justification = "top" ,
legend.title = element_text(hjust = 0.5)# Aligns the legend to the right edge
)
Combined_Ten_thousand_distance<-ggdraw() +
theme(plot.background = element_rect(fill="white", color = NA))+
draw_plot(Ten_thousand_plot_distance, x = 0, y = 0.0, width =1 , height = 1) +
draw_plot(Ten_thousands_error_distribution_distance, x = 0.8, y = 0.08, width =.2 , height = 0.5)
##Now same fpr azimuth
Table2$N_Vector_Azimuth_No_Shift_atan2<-as.circular(Table2$N_Vector_Azimuth_No_Shift, type = "angles", units ="degrees", template = "geographics")
Table2$Azimuth_rhumb_geo<-as.circular(Table2$Azimuth_rhumb_geo, type = "angles", units ="degrees", template = "geographics")
Table2$angular_diff<-Table2$N_Vector_Azimuth_No_Shift_atan2-Table2$Azimuth_rhumb_geo
Table2$angular_diff<-as.numeric(Table2$angular_diff)
Table2$abs_angular_diff<-abs(Table2$angular_diff)
Table2$N_Vector_Azimuth_No_Shift_atan2<-as.numeric(Table2$N_Vector_Azimuth_No_Shift_atan2)
Table2$Azimuth_rhumb_geo<-as.numeric(Table2$Azimuth_rhumb_geo)
Table2$abs_angular_diff<-as.numeric(Table2$abs_angular_diff)
Table2$angular_diff<-as.numeric(Table2$angular_diff)
Table2$angular_diff<-ifelse(Table2$angular_diff>359,0,Table2$angular_diff)#These mean 0 difference
Table2$angular_diff<-ifelse(Table2$angular_diff>179,0,Table2$angular_diff)#single one, milimeters apart
Table2$abs_angular_diff<-as.numeric(abs(Table2$angular_diff))
#Mechanism output vs real distance
Hundred<-Table2%>%filter(range==100)
#100km
Hundreds_error_distribution_azimuth<-ggplot(Hundred, aes(x = angular_diff)) +
geom_histogram(aes(y = after_stat(count / sum(count)))) +
scale_y_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "Error\ndistribution")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
Hundred_plot_azimuth<-ggplot(Hundred, aes(x = Azimuth_rhumb_geo, y = N_Vector_Azimuth_No_Shift)) +
geom_point(aes(color=abs_angular_diff),size=0.1) +
geom_smooth(method = "lm",color = "blue") + # Adds linear regression line
labs(x = "Angle = Rhumb azimuth (deg)",
y = "Radial distance = Mechanism output (deg)")+scale_y_continuous(expand = (0),breaks = c(0, 45, 90,135,180,224,270,315,360),limits = c(0, 360))+
stat_regline_equation(label.y = 360,label.x = 230, aes(label = paste(..eq.label.., ..rr.label.., sep = "~~~~"))) +
theme_minimal()+coord_polar()+
scale_color_continuous(
name = "Error\nsize (°)", # Set the legend title
guide = guide_colorbar(
barwidth = unit(0.2, "cm"),
barheight = unit(2, "cm")
))+
theme(
legend.position = "right", # Places the legend above the plot
legend.justification = "top" # Aligns the legend to the right edge
)+scale_x_continuous(breaks = c(0, 45, 90,135,180,224,270,315,360)) +
expand_limits(x = 0)
Combined_hundred_azimuth<-ggdraw() +
theme(plot.background = element_rect(fill="white", color = NA))+
draw_plot(Hundred_plot_azimuth, x = 0, y = 0.0, width =1 , height = 1) +
draw_plot(Hundreds_error_distribution_azimuth, x = 0.8, y = 0.08, width =.2 , height = 0.45)
#1000km
Thousand<-Table2%>%filter(range==1000)##Maybe increase sample size
Thousand_error_distribution_azimuth<-ggplot(Thousand, aes(x = angular_diff)) +
geom_histogram(aes(y = after_stat(count / sum(count)))) +
scale_y_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "Error\ndistribution")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
Thousand_plot_azimuth<-ggplot(Thousand,aes(x = Azimuth_rhumb_geo, y = N_Vector_Azimuth_No_Shift)) +
geom_point(aes(color=abs_angular_diff),size=0.1) +
geom_smooth(method = "lm", col = "blue") + # Adds linear regression line
labs(x = "Angle = Rhumb azimuth (deg)",
y = "Radial distance = Mechanism output (deg)")+scale_y_continuous(expand = (0),,breaks = c(0, 45, 90,135,180,224,270,315,360),limits = c(0, 360))+
stat_regline_equation(label.y = 360,label.x = 230, aes(label = paste(..eq.label.., ..rr.label.., sep = "~~~~"))) +
theme_minimal()+coord_polar()+
scale_color_continuous(
name = "Error\nsize (°)", # Set the legend title
guide = guide_colorbar(
barwidth = unit(0.2, "cm"),
barheight = unit(2, "cm")
))+
theme(
legend.position = "right", # Places the legend above the plot
legend.justification = "top" # Aligns the legend to the right edge
)+scale_x_continuous(breaks = c(0, 45, 90,135,180,224,270,315,360)) +
expand_limits(x = 0)
Combined_thousand_azimuth<-ggdraw() +
theme(plot.background = element_rect(fill="white", color = NA))+
draw_plot(Thousand_plot_azimuth, x = 0, y = 0.0, width =1 , height = 1) +
draw_plot(Thousand_error_distribution_azimuth, x = 0.8, y = 0.08, width =.2 , height = 0.45)
#10000km
Ten_thousand<-Table2%>%filter(range==20000)
Ten_thousand_error_distribution_azimuth<-ggplot(Ten_thousand, aes(x = angular_diff)) +
geom_histogram(aes(y = after_stat(count / sum(count)))) +
scale_y_continuous(labels = scales::percent) +theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),axis.title.y = element_blank())+labs(title = "Error\ndistribution")+ theme(plot.title = element_text(size = 10,hjust = 0.5),axis.text.y = element_blank(),axis.title.x = element_blank())
Ten_thousand_plot_azimuth<-ggplot(Ten_thousand,aes(x = Azimuth_rhumb_geo, y = N_Vector_Azimuth_No_Shift)) +
geom_point(aes(color=abs_angular_diff),size=0.1) +
geom_smooth(method = "lm", col = "blue") + # Adds linear regression line
labs(x = "Angle = Rhumb azimuth (deg)",
y = "Radial distance = Mechanism output (deg)")+scale_y_continuous(expand = (0),,breaks = c(0, 45, 90,135,180,224,270,315,360),limits = c(0, 360))+
stat_regline_equation(label.y = 360,label.x = 230, aes(label = paste(..eq.label.., ..rr.label.., sep = "~~~~"))) +
theme_minimal()+coord_polar()+
scale_color_continuous(
name = "Error\nsize (°)", # Set the legend title
guide = guide_colorbar(
barwidth = unit(0.2, "cm"),
barheight = unit(2, "cm")
))+
theme(
legend.position = "right", # Places the legend above the plot
legend.justification = "top" # Aligns the legend to the right edge
)+scale_x_continuous(breaks = c(0, 45, 90,135,180,224,270,315,360)) +
expand_limits(x = 0)
Combined_ten_thousand_azimuth<-ggdraw() +
theme(plot.background = element_rect(fill="white", color = NA))+
draw_plot(Ten_thousand_plot_azimuth, x = 0, y = 0.0, width =1 , height = 1) +
draw_plot(Ten_thousand_error_distribution_azimuth, x = 0.8, y = 0.08, width =.2 , height = 0.45)
##How many are accuarte here?
hist(Ten_thousand$angular_diff)
t<-Ten_thousand%>%filter(angular_diff<1)
t<-t%>%filter(angular_diff>-1)
filtered_df <- Ten_thousand %>%
filter(angular_diff >= -5 & angular_diff <= 5)
filtered_df <- Ten_thousand %>%
filter(Distance_diff_rel >= -5 & angular_diff <= 5)
#make the plot
vector_mechanism_summary<-ggdraw() +
theme(plot.background = element_rect(fill="white", color = NA))+
draw_plot(Combined_hundered_distance, x = 0, y = 0.66, width =0.5 , height = .33) +
draw_plot(Combined_hundred_azimuth, x = 0.5, y = 0.66, width =0.5 , height = .33) +
draw_plot(Combined_Thousand_distance, x = 0., y = 0.33, width =0.5 , height = .33) +
draw_plot(Combined_thousand_azimuth, x = 0.5, y = 0.33, width =0.5 , height = .33) +
draw_plot(Combined_Ten_thousand_distance, x = 0., y = 0., width =0.5 , height = .33) +
draw_plot(Combined_ten_thousand_azimuth, x = 0.5, y = 0., width =0.5 , height = .33) +
draw_line(x = c(0, 1), y = c(.66, .66), color = "black",size = 0.5)+
draw_line(x = c(0, 1), y = c(.33, .33), color = "black",size = 0.5)+
draw_label("100 KM,", x = 0.5, y = 0.675, size = 18, fontface = "bold") +
draw_label("1,000 KM,", x = 0.5, y = 0.345, size = 18, fontface = "bold") +
draw_label("20,000 KM,", x = 0.5, y = 0.015, size = 18, fontface = "bold")+
draw_label(" N=100,000", x = 0.61, y = 0.672, size = 12, fontface = "bold") +
draw_label(" N=100,000", x = 0.625, y = 0.342, size = 12, fontface = "bold") +
draw_label(" N=100,000", x = 0.63, y = 0.012, size = 12, fontface = "bold") +
draw_label(" A.", x = 0.01, y = 0.98, size = 12, fontface = "bold")+
draw_label(" i.", x = 0.025, y = 0.978, size = 8, fontface = "bold")+
draw_label(" ii.", x = 0.5, y = 0.978, size = 8, fontface = "bold")+
draw_label(" B.", x = 0.01, y = 0.65, size = 12, fontface = "bold")+
draw_label(" i.", x = 0.025, y = 0.648, size = 8, fontface = "bold")+
draw_label(" ii.", x = 0.5, y = 0.648, size = 8, fontface = "bold")+
draw_label(" C.", x = 0.01, y = 0.32, size = 12, fontface = "bold")+
draw_label(" i.", x = 0.025, y = 0.318, size = 8, fontface = "bold")+
draw_label(" ii.", x = 0.5, y = 0.318, size = 8, fontface = "bold")
ggsave("vector_no_shift_summary_3.5.png", width =8 , height =10,dpi=300)
#Composit plot of other parameters vs relative error
#Date
#Day length
#Time from sunrise
#Lats
#Lons
```
Figure 5
Time Shift
```{r}
load("Supplamentary_data")
unique(Table2$Time_shift)
##אני חושב שמה שקורה זה שב1 ו2 אנחנו רואים בערך את האפקט של השיפט + ממוצע הסטייה בלי שיפט. כך שעולים בשיפט
##Add time shift driven change in hour angle
Table2$Time_shift<-as.numeric(Table2$Time_shift)
unique(Table2$Time_shift)
Table2$Shift_effect<-Table2$Time_shift*180/Table2$Day_length##Added change in ohur angle - Allways positive
##Calculate the observed hour angle based on the Expected formula (which uses time) and the difference in longitude between displacement and home.
Table2$Observed_hour_angle_shift<-Table2$Time_from_sunrise*180/Table2$Day_length+(Table2$Longitude_displacement-Table2$Longitude_home)+Table2$Shift_effect
Table2$Expected_hour_angle_displacement<-Table2$Time_from_sunrise*180/Table2$Day_length
##Filter only home-displacement combinations that produce obsered hour angles between 0-180, below which and above which the sun is not in the sky
##at dispalcement. Expected hour angle doesnt need filtering becuase the forula restricts it to 0-180
Table2<-Table2%>%filter(as.numeric(Observed_hour_angle)>0)
Table2<-Table2%>%filter(as.numeric(Observed_hour_angle)<180)
###Scenarios with shift effect larger than the remainig hour angle range are unrealistic and should be dropped from teh dataset
##If the shift effect is larger than the daylight time remaining -expreseed as hour angle range left to move
##through the day given time from sunrise and day length, then the sun will set and its not in the game.
###############################################################################################################
Table2$Shift_effect_real<-ifelse(Table2$Observed_hour_angle_shift<180,"Yes","No")
##Real
Table2<-Table2%>%filter(Shift_effect_real=="Yes")
Table2$angular_diff_vec<-Table2$N_Vector_Azimuth_Shifted-Table2$Azimuth_rhumb_geo
range(Table2$angular_diff_vec)
#Table2$angular_diff_vec<-ifelse(Table2$angular_diff_vec<0,Table2$angular_diff_vec+360,Table2$angular_diff_vec)
#Table2$angular_diff_vec<-ifelse(Table2$angular_diff_vec>180,360-Table2$angular_diff_vec,Table2$angular_diff_vec)
Table2$angular_diff_bin<-Table2$N_Binary_Shifted-Table2$Azimuth_rhumb_geo
range(Table2$angular_diff_bin)
#Table2$angular_diff_bin<-ifelse(Table2$angular_diff_bin<0,Table2$angular_diff_bin+360,Table2$angular_diff_bin)
#Table2$angular_diff_bin<-ifelse(Table2$angular_diff_bin>180,360-Table2$angular_diff_bin,Table2$angular_diff_bin)
#range(Table2$angular_diff2)
##בוקס שמראה את האאוטפוט של השיפט מול האאופוט של הנון שיפטד
##Calculate the relative size of the error - relative to the geosphere output of shortest distance
Table2<-Table2%>%filter(Latitude_home>=0)
Table2<-Table2%>%filter(Longitude_home>=0)
test_results<-Table2%>%
group_by(range,Time_shift)%>%
dplyr::summarise(sample_size=n(),
Shift_effect=mean(Shift_effect),
median_angular_diff_vec=median(as.numeric(angular_diff_vec)),
median_angular_diff_bin=median(as.numeric(angular_diff_bin))
)
#Table3<-Table2
t<-test_results
t$vec_bin_diff<-t$median_angular_diff_vec
t$mechanism<-rep("vec",nrow(t))
t2<-test_results
t2$vec_bin_diff<-t2$median_angular_diff_bin
t2$mechanism<-rep("bin",nrow(t2))
test_results<-rbind(t,t2)
test_results$range<-factor(test_results$range)
test_results$mechanism<-ifelse(test_results$mechanism=="bin","Binary Mechanism", "Vector Mechanism")
test_results$range<-ifelse(test_results$range==100,"100",ifelse(test_results$range==1000,"1,000","20,000"))
test_results$range<-factor(test_results$range,levels=c("100","1,000","20,000"))
Mean_angular_diff_plot<-ggplot(test_results, aes(x = Time_shift, y =vec_bin_diff,fill = range )) +
geom_point(shape=21,color="black",size = 1) +geom_smooth(aes(color=range),se=F)+scale_fill_manual(values = c("lightblue1","lightblue3","lightblue4"))+scale_color_manual(values = c("lightblue1","lightblue3","lightblue4"))+theme_minimal()+theme(legend.position = "bottom")+facet_wrap(.~mechanism,ncol=2)+theme(strip.text = element_text(size = 14,face = "bold"))+scale_y_continuous(breaks = seq(-110, 160, by = 10),expand = c(0,0))+scale_x_continuous(breaks=seq(-6,6,by=0.5))+theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))+labs(fill= "Displacement range (km)",color="Displacement range (km)")+ylab("[Shited function azimuth output - Real homing azimuth] (degrees)")+xlab("Clock shift (hours)")
Table2$range<-factor(Table2$range)
Table2$Time_shift_round<-round(Table2$Time_shift,digits = 0)
Table2$Time_shift_round<-factor(Table2$Time_shift_round,levels = c(-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6))
Distance_vec<-ggplot(data = Table2, aes(x = distance_km_rhumb_geo, y = angular_diff_vec, color = Time_shift_round)) +
geom_smooth(method = "lm",se=F) +
theme_minimal()+scale_color_manual(values=c("#191970","#2b418a","#4f71a4","#7aa0c0","#b6d6e6","#bfefff","black","#FF8DA1","#FF708C","#FF3E60","#DC143C","#A52A2A","#8B0000"))+theme(legend.position = "right")+labs(color = "Clock\nshift\n(hours)")
Distance_bin<-ggplot(data = Table2, aes(x = distance_km_rhumb_geo, y = angular_diff_bin, color = Time_shift_round)) +
geom_smooth(method = "lm") + guides(color = guide_legend(override.aes = list(fill = NA), reverse = TRUE))+
theme_minimal()+scale_color_manual(values=c("#191970","#2b418a","#4f71a4","#7aa0c0","#b6d6e6","#bfefff","black","#FF8DA1","#FF708C","#FF3E60","#DC143C","#A52A2A","#8B0000"))+theme(legend.position = "right")+labs(color = "Clock\nshift\n(hrs)")+xlab("Displacement distace \n(km)")+ylab("[Shited function azimuth output - Real homing azimuth] (degrees)")+scale_x_continuous(breaks=seq(0,20000,by=2000) ,labels = label_number(scale_cut = cut_short_scale()))+theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))+scale_y_continuous(breaks = seq(-125, 130, by = 10),expand = c(0,0))+coord_cartesian(ylim = c(-125, 125))+
theme(legend.key.width = unit(0.2, "cm"))
Table2$shift<-ifelse(Table2$Shift_effect==0,"None",ifelse(Table2$Shift_effect<0,"Slow","Fast"))
Table2$shift<-factor(Table2$shift,levels = c("Slow","None","Fast"))
Shift_effect_latitude<-ggplot(data = Table2, aes(x = Latitude_displacement, y = angular_diff_bin, color = shift)) +
geom_smooth() +
theme_minimal()+scale_color_manual(values=c("#7aa0c0","black","#DC143C"))+theme(legend.position = "none")+labs(color = "Shift type")+xlab("Displacement Latitude \n(deg)")+scale_y_continuous(breaks = seq(-125, 130, by = 10),expand = c(0,0))+scale_x_continuous(breaks = seq(0, 90, by = 10),expand = c(0,0))+ylab("[Shited function azimuth output - Real homing azimuth] (degrees)")+theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
##Remove instances where the shift effect goes over sunset or befire sunrise
Table3<-Table2
Table3$t<-ifelse(Table3$Shift_effect+Table3$Observed_hour_angle_shift<0,T,F)
Table3<-Table3%>%filter(t!=T)
Table3$t<-ifelse(Table3$Shift_effect+Table3$Observed_hour_angle_shift>180,T,F)
Table3<-Table3%>%filter(t!=T)
Shift_effect_plot<-ggplot(Table3, aes(x = factor(Time_shift_round), y = Shift_effect)) +
geom_boxplot(outlier.size = 0.5,fill="lightblue1") +theme_minimal()+theme(legend.position = "none")+ylim(-180,180)+xlab("Clock shift \n(hours)")+ylab("Shift effect (hour angle degrees)")+scale_y_continuous(breaks = seq(-180, 180, by = 10),expand = c(0,0))
plot<-ggdraw() +
draw_plot(Shift_effect_plot, x = 0, y = 0.5, width =0.28, height = 0.5) +
draw_plot(Shift_effect_latitude, x = 0.285, y = 0.5, width =0.28, height = 0.5) +
draw_plot(Distance_bin, x = 0.57, y = 0.5, width =0.44, height = .5) +
draw_plot( Mean_angular_diff_plot, x = 0., y = 0., width =1, height = .5) + theme(plot.background = element_rect(fill="white", color = NA))+
draw_label(" A.", x = 0.01, y = 0.99, size = 12, fontface = "bold")+
draw_label(" B.", x = 0.28, y = 0.99, size = 12, fontface = "bold")+
draw_label(" C.", x = 0.56, y = 0.99, size = 12, fontface = "bold")+
draw_label(" D.", x = 0.04, y = 0.48, size = 12, fontface = "bold") +
draw_label(" Fast shifts (+)", x = 0.45, y = 0.98, size = 10, fontface = "bold",color ="#8B0000" ) +
draw_label(" No shift", x = 0.45, y = 0.79, size = 10, fontface = "bold") +
draw_label(" Slow shifts (-)", x = 0.45, y = 0.58, size = 10, fontface = "bold",color="#191970")
ggsave("Shift_plot2a.png", width = 7, height = 10,dpi=300)
```
Table 1
```{r}
load("Supplamentary_data")
#load("Simulation_data_V9.1_Time_shift_with_decimal_corrected")
#plots:
#Mechanism output vs real distance
##North
Table2$Distance_diff<-Table2$N_Vector_distance_No_Shift-Table2$distance_km_geo
#Looks like our function estiamte has more larger then shorter distances compared - maybe because its the geosphere outputs shortest difference and we scalculate fixed azimuth. Test geosphere's rhumb distance as well
##Calculate the relative size of the error - relative to the geosphere output of shortest distance
Table2$Distance_diff_rel<-Table2$Distance_diff/Table2$distance_km_geo
Table2$Distance_diff_rel_abs<-abs(Table2$Distance_diff/Table2$distance_km_geo)
##Now same fpr azimuth
Table2$N_Vector_Azimuth_No_Shift_atan2<-as.circular(Table2$N_Vector_Azimuth_No_Shift, type = "angles", units ="degrees", template = "geographics")
Table2$Azimuth_rhumb_geo<-as.circular(Table2$Azimuth_rhumb_geo, type = "angles", units ="degrees", template = "geographics")
Table2$angular_diff<-Table2$N_Vector_Azimuth_No_Shift_atan2-Table2$Azimuth_rhumb_geo
Table2$angular_diff<-as.numeric(Table2$angular_diff)
Table2$abs_angular_diff<-abs(Table2$angular_diff)
Table2$N_Vector_Azimuth_No_Shift_atan2<-as.numeric(Table2$N_Vector_Azimuth_No_Shift_atan2)
Table2$Azimuth_rhumb_geo<-as.numeric(Table2$Azimuth_rhumb_geo)
Table2$abs_angular_diff<-as.numeric(Table2$abs_angular_diff)
Table2$angular_diff<-as.numeric(Table2$angular_diff)
Table2$angular_diff<-ifelse(Table2$angular_diff>359,0,Table2$angular_diff)#These mean 0 difference
Table2$angular_diff<-ifelse(Table2$angular_diff>179,0,Table2$angular_diff)#single one, milimeters apart
Table2$abs_angular_diff<-as.numeric(abs(Table2$angular_diff))
Table2$N_Binary_No_Shift<-as.circular(Table2$N_Binary_No_Shift, type = "angles", units ="degrees", template = "geographics")
Table2$Azimuth_rhumb_geo<-as.circular(Table2$Azimuth_rhumb_geo, type = "angles", units ="degrees", template = "geographics")
Table2$angular_diff_binary<-Table2$N_Binary_No_Shift-Table2$Azimuth_rhumb_geo
Table2$angular_diff_binary<-as.numeric(Table2$angular_diff_binary)
Table2$abs_angular_diff_binary<-abs(Table2$angular_diff_binary)
Table2$N_Binary_No_Shift<-as.numeric(Table2$N_Binary_No_Shift)
Table2$Azimuth_rhumb_geo<-as.numeric(Table2$Azimuth_rhumb_geo)
Table2$abs_angular_diff_binary<-as.numeric(Table2$abs_angular_diff_binary)
Table2$angular_diff_binary<-as.numeric(Table2$angular_diff_binary)
Table2$abs_angular_diff_binary<-as.numeric(abs(Table2$angular_diff_binary))
Table2$angular_diff_binary<-ifelse(Table2$angular_diff_binary>359,0,Table2$angular_diff_binary)#These mean 0 difference
Table2$angular_diff_binary<-ifelse(Table2$angular_diff_binary>179,0,Table2$angular_diff_binary)#single one, milimeters apart
Table_North<-Table2 %>%
group_by(range) %>%
summarize(n=n(),
Mean_distance_rel=mean(Distance_diff_rel_abs),
SD_distance_rel=sd(Distance_diff_rel_abs),
max_distance_rel=max(Distance_diff_rel_abs),
Percentile_95_distance_rel = quantile(Distance_diff_rel_abs, 0.95, na.rm = TRUE),
Mean_distance=mean(abs(Distance_diff)),
SD_distance=sd(abs(Distance_diff)),
max_distance=max(abs(Distance_diff)),
Percentile_95_distance = quantile(abs(Distance_diff), 0.95, na.rm = TRUE),
Mean_azimuth_diff=mean(abs_angular_diff),
SD_azimuth_diff=sd(abs_angular_diff),
max_azimuth_diff=max(abs_angular_diff),
Percentile_95_azimuth = quantile(abs_angular_diff, 0.95, na.rm = TRUE),
Mean_azimuth_diff_binary=mean(abs_angular_diff_binary),
SD_azimuth_diff_binary=sd(abs_angular_diff_binary),
max_azimuth_diff_binary=max(abs_angular_diff_binary),
Percentile_95_azimuth_binary = quantile(abs_angular_diff_binary, 0.95, na.rm = TRUE),)
##South
Table2$Distance_diff<-Table2$S_Vector_distance_No_Shift-Table2$distance_km_geo
#Looks like our function estiamte has more larger then shorter distances compared - maybe because its the geosphere outputs shortest difference and we scalculate fixed azimuth. Test geosphere's rhumb distance as well
##Calculate the relative size of the error - relative to the geosphere output of shortest distance
Table2$Distance_diff_rel<-Table2$Distance_diff/Table2$distance_km_geo
Table2$Distance_diff_rel_abs<-abs(Table2$Distance_diff/Table2$distance_km_geo)
##Now same fpr azimuth
Table2$S_Vector_Azimuth_No_Shift<-as.circular(Table2$S_Vector_Azimuth_No_Shift, type = "angles", units ="degrees", template = "geographics")
Table2$Azimuth_rhumb_geo<-as.circular(Table2$Azimuth_rhumb_geo_S, type = "angles", units ="degrees", template = "geographics")
Table2$angular_diff<-Table2$S_Vector_Azimuth_No_Shift-Table2$Azimuth_rhumb_geo_S
Table2$angular_diff<-as.numeric(Table2$angular_diff)
Table2$abs_angular_diff<-abs(Table2$angular_diff)
Table2$S_Vector_Azimuth_No_Shift<-as.numeric(Table2$S_Vector_Azimuth_No_Shift)
Table2$Azimuth_rhumb_geo<-as.numeric(Table2$Azimuth_rhumb_geo_S)
Table2$abs_angular_diff<-as.numeric(Table2$abs_angular_diff)
Table2$angular_diff<-as.numeric(Table2$angular_diff)
Table2$angular_diff<-ifelse(Table2$angular_diff>359,0,Table2$angular_diff)#These mean 0 difference
Table2$angular_diff<-ifelse(Table2$angular_diff>179,0,Table2$angular_diff)#single one, milimeters apart
Table2$abs_angular_diff<-as.numeric(abs(Table2$angular_diff))
Table2$S_Binary_No_Shift<-as.circular(Table2$S_Binary_No_Shift, type = "angles", units ="degrees", template = "geographics")
Table2$Azimuth_rhumb_geo<-as.circular(Table2$Azimuth_rhumb_geo, type = "angles", units ="degrees", template = "geographics")
Table2$angular_diff_binary<-Table2$S_Binary_No_Shift-Table2$Azimuth_rhumb_geo_S
Table2$angular_diff_binary<-as.numeric(Table2$angular_diff_binary)
Table2$abs_angular_diff_binary<-abs(Table2$angular_diff_binary)
Table2$S_Binary_No_Shift<-as.numeric(Table2$S_Binary_No_Shift)
Table2$Azimuth_rhumb_geo<-as.numeric(Table2$Azimuth_rhumb_geo)
Table2$abs_angular_diff_binary<-as.numeric(Table2$abs_angular_diff_binary)
Table2$angular_diff_binary<-as.numeric(Table2$angular_diff_binary)
Table2$angular_diff_binary<-ifelse(Table2$angular_diff>359,0,Table2$angular_diff_binary)#These mean 0 difference
Table2$angular_diff_binary<-ifelse(Table2$angular_diff>179,0,Table2$angular_diff_binary)#single one, milimeters apart
Table2$abs_angular_diff_binary<-as.numeric(abs(Table2$angular_diff_binary))
range(Table2$angular_diff_binary)
Table_South<-Table2 %>%
group_by(range) %>%
summarize(n=n(),
Mean_distance_rel=mean(Distance_diff_rel_abs),
SD_distance_rel=sd(Distance_diff_rel_abs),
max_distance_rel=max(Distance_diff_rel_abs),
Percentile_95_distance_rel = quantile(Distance_diff_rel_abs, 0.95, na.rm = TRUE),
Mean_distance=mean(abs(Distance_diff)),
SD_distance=sd(abs(Distance_diff)),
max_distance=max(abs(Distance_diff)),
Percentile_95_distance = quantile(abs(Distance_diff), 0.95, na.rm = TRUE),
Mean_azimuth_diff=mean(abs_angular_diff),
SD_azimuth_diff=sd(abs_angular_diff),
max_azimuth_diff=max(abs_angular_diff),
Percentile_95_azimuth = quantile(abs_angular_diff, 0.95, na.rm = TRUE),
Mean_azimuth_diff_binary=mean(abs_angular_diff_binary),
SD_azimuth_diff_binary=sd(abs_angular_diff_binary),
max_azimuth_diff_binary=max(abs_angular_diff_binary),
Percentile_95_azimuth_binary = quantile(abs_angular_diff_binary, 0.95, na.rm = TRUE),)
```