## Enhanced Classifier ###
# Load packages
::source_url("https://github.com/r2j2ritson/RSpatial_Wildlife/blob/main/R/coords_as_sf.R?raw=TRUE")
devtools::source_url("https://github.com/r2j2ritson/RSpatial_Wildlife/blob/main/R/instaload.R?raw=TRUE")
devtoolsinstaload(c('data.table','lubridate','plyr','zoo','mapboxer','rmarkdown','markdown','tinytex',
'ggplot2','ggmap','dplyr'))
#### USER INPUT - set up directories; create file copy to overwrite classifications
<- "mule deer"
species <- "K:/Wildlife/sbergen/forRitson/nsd/ID_MD_2019_NSD"
inpath <- "C:/Users/rritson/Documents/Projects/NSD/sandbox"
scriptdir setwd(inpath) # change working directory to deer or elk folder
=5
i<- paste0("Sel",i)
herd <- paste0("ID_MD_2019_locs_cleaned_NSD_sel",i,"_go.csv")
file <- paste0(getwd(), "/unclassified_data")
rawdir <- paste0(getwd(), "/classified_data")
datadir <- paste0(datadir, "/", file)
outfile ###
# Read in the file prepared in last script
<- outfile %>%
all_recs fread(., header = TRUE, stringsAsFactors = FALSE) %>%
::rowwise(.) %>%
dplyr::mutate(GMT = as.POSIXct(paste0(Year,"-",Month,"-",Day," ",Hour,":",Minute,":",Second),
dplyrformat = "%Y-%m-%d %H:%M:%S", tz = "GMT")) %>%
::ungroup(.) %>%
dplyras.data.frame(.)
str(all_recs)
<- unique(year(all_recs$GMT))
yrs <- sort(yrs)
yrs #######################
= 0
savecounter
# Prep Color Palette
<- data.frame("Habitat" = c("Discard",
hab_palette "Not assigned",
"Not assigned",
"blank",
"Winter",
"Winter",
"Summer",
"Summer",
"SpringMig",
"FallMig",
"Resident",
"Nomad"),
"color" = c("#BEBEBE",
"#000000",
"#000000",
"#000000",
"#0000FF",
"#BFEFFF",
"#FFFF00",
"#EEDD82",
"#B8860B",
"#008000",
"#FF00FF",
"#40E0D0"),
"Hab_code" =c("Discard",
"not assigned",
NA,
"",
"winter",
"wntmov",
"summer",
"summov",
"fallmig",
"sprmig",
"Resident",
"Nomad"))
# Classify Dates Function
<- function(id_recs){
classify_dates ## Look-up Tables
<- id_recs %>%
spring_lut ::filter(Hab_code == "sprmig") %>%
dplyr::group_by(habitat) %>%
dplyr::summarise(Start = min(GMT),
dplyrEnd = max(GMT)) %>%
::arrange(.,Start)
dplyr
<- id_recs %>%
fall_lut ::filter(Hab_code == "fallmig") %>%
dplyr::group_by(habitat) %>%
dplyr::summarise(Start = min(GMT),
dplyrEnd = max(GMT)) %>%
::arrange(.,Start)
dplyr
## Func Codes
<- function(){
last_summer paste0("summer", (as.numeric(year)-1))
}<- function(){
last_winter paste0("winter", (as.numeric(year)-1))
}<- function(){
next_summer paste0("summer", (as.numeric(year)+1))
}<- function(){
next_winter paste0("winter", (as.numeric(year)+1))
}<- function(){
current_summer paste0("summer", year)
}<- function(){
current_winter paste0("winter", year)
}
## Classify Dates
### Only One Spring Migration classified
if(nrow(spring_lut) == 1 & nrow(fall_lut) == 0){ #classic partial sequence
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT < spring_lut$Start,
id_recscurrent_winter(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT > spring_lut$End,
id_recscurrent_summer(), id_recs$habitat)
}### Only One Fall Migration classified
if(nrow(spring_lut) == 0 & nrow(fall_lut) == 1){
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT < fall_lut$Start,
id_recslast_summer(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT > fall_lut$End,
id_recscurrent_winter(), id_recs$habitat)
}### One Spring and One Fall Migration classified
if(nrow(spring_lut) == 1 & nrow(fall_lut) == 1){
if(spring_lut$Start < fall_lut$Start){ #Classic complete sequence
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT < spring_lut$Start,
id_recscurrent_winter(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT > spring_lut$End & id_recs$GMT < fall_lut$Start,
id_recscurrent_summer(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT > fall_lut$End,
id_recsnext_winter(), id_recs$habitat)
else{
}$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT < fall_lut$Start,
id_recslast_summer(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT > fall_lut$End & id_recs$GMT < spring_lut$Start,
id_recscurrent_winter(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT > spring_lut$End,
id_recscurrent_summer(), id_recs$habitat)
}
}### Two Fall Migrations and One Spring Spring Migration classified
if(nrow(spring_lut) == 1 & nrow(fall_lut) == 2){
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT < fall_lut$Start[1],
id_recslast_summer(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT < spring_lut$Start & id_recs$GMT > fall_lut$End[1],
id_recscurrent_winter(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT > spring_lut$End & id_recs$GMT < fall_lut$Start[2],
id_recscurrent_summer(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT > fall_lut$End[2],
id_recsnext_winter(), id_recs$habitat)
}### One Fall Migrations and Two Spring Spring Migration classified
if(nrow(spring_lut) == 2 & nrow(fall_lut) == 1){
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT < spring_lut$Start[1],
id_recscurrent_winter(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT > spring_lut$End[1] & id_recs$GMT < fall_lut$Start,
id_recscurrent_summer(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT > fall_lut$End & id_recs$GMT < spring_lut$Start[2],
id_recsnext_winter(), id_recs$habitat)
$habitat <- ifelse(id_recs$color == "#000000" & id_recs$GMT > spring_lut$End[2],
id_recsnext_summer(), id_recs$habitat)
}### Add Years to Winter and Summer Movements
$Hab_code <- stringr::str_split_fixed(id_recs$habitat,"[:digit:]",2)[,1]
id_recs<- id_recs %>%
winter_lut ::filter(Hab_code == "winter") %>%
dplyr::group_by(habitat) %>%
dplyr::summarise(Start = min(GMT),
dplyrEnd = max(GMT)) %>%
::arrange(.,Start) %>%
dplyr::rowwise(.) %>%
dplyr::mutate(Year = stringr::str_split_fixed(habitat,"winter",2)[,2]) %>%
dplyr::ungroup(.) %>%
dplyras.data.frame(.)
<- id_recs %>%
summer_lut ::filter(Hab_code == "summer") %>%
dplyr::group_by(habitat) %>%
dplyr::summarise(Start = min(GMT),
dplyrEnd = max(GMT)) %>%
::arrange(.,Start) %>%
dplyr::rowwise(.) %>%
dplyr::mutate(Year = stringr::str_split_fixed(habitat,"summer",2)[,2]) %>%
dplyr::ungroup(.) %>%
dplyras.data.frame(.)
if(nrow(winter_lut) >=1){
for(i in 1:nrow(winter_lut)){
$habitat <- ifelse(id_recs$habitat == "wntmov" & id_recs$GMT > winter_lut$Start[i] & id_recs$GMT < winter_lut$End[i],
id_recspaste0("wntmov", winter_lut$Year[i]), id_recs$habitat)
}
}if(nrow(summer_lut) >=1){
for(i in 1:nrow(summer_lut)){
$habitat <- ifelse(id_recs$habitat == "summov" & id_recs$GMT > summer_lut$Start[i] & id_recs$GMT < summer_lut$End[i],
id_recspaste0("summov", winter_lut$Year[i]), id_recs$habitat)
}
}
$Hab_code <- NULL
id_recs$color <- NULL
id_recs$Hab_code <- stringr::str_split_fixed(id_recs$habitat,"[:digit:]",2)[,1]
id_recs<- dplyr::left_join(id_recs,hab_palette[,c(-1)],by="Hab_code")
id_recs return(id_recs)
}
# Begin Year loop
for(y in 1:length(yrs)){
print(paste("Looking for year", yrs[y], "records needing classification"))
## Set-up ###
# Subset dataset yr by yr; Jan-Feb of next yr kept too in case fall migration carries over
<- all_recs[year(all_recs$GMT) == yrs[y] |
yr_recs year(all_recs$GMT) == yrs[y] + 1 &
month(all_recs$GMT) < 5, ]
# Read in overall notes table
<- read.csv(paste0(getwd(), "/unsorted_output/", herd, "/", yrs[y],
notes_tab "/", yrs[y], "_overall.csv"), header = TRUE)
<- lapply(notes_tab, as.character)
notes_tab[]
## Create list of individuals to analyze ###
if(exists("id_list")){
if(! is.null(id_list)){
<- id_list
individs_list else {
} <- readline("Pick-up where you left off (pu) OR review all (ra)? ")
fb if(fb == "pu"){
<- notes_tab[is.na(notes_tab$Skip) | notes_tab$Skip == "", ]$Animal_ID
individs_list else{
}<- notes_tab$Animal_ID
individs_list
}
}else {
} <- readline("Pick-up where you left off (pu) OR review all (ra)? ")
fb if(fb == "pu"){
<- notes_tab[is.na(notes_tab$Skip) | notes_tab$Skip == "", ]$Animal_ID
individs_list else{
}<- notes_tab$Animal_ID
individs_list
}
}<- individs_list[which(individs_list %in% all_recs$Animal_ID)]
individs_list # If empty, review revisits?
if(length(individs_list) == 0){
<- readline("No individuals left to be classified. Review revisits? Y or N ")
revisit if(revisit == "Y"){
<- notes_tab[notes_tab$Skip == "N" & notes_tab$Revisit == "Y", ]$Animal_ID
individs_list <- individs_list[which(individs_list %in% all_recs$Animal_ID)]
individs_list
}
}if(length(individs_list)==0){
message("There are no revisits remaining in this file.")
next
}
## Begin Migration Analysis ###
# Individual loop
for(id in 1:length(individs_list)){
# Check previous plots if revisiting...
if(revisit == "Y"){
## Query previous NSDs
source("K:/Wildlife/sbergen/forRitson/nsd/ID_MD_2019_NSD/query_previous_nsds.R")
find_nsds(id = individs_list[id], species = species)
## What are we checking?
if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Skip == "Y"){
message("This individual was previously skipped.")
else if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Strategy == "M"){
}message("This individual was previously labeled a migrant.")
else if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Strategy == "MM"){
}message("This individual was previously labeled a mixed-migrant.")
else if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Strategy == "R"){
}message("This individual was previously labeled a resident.")
else if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Strategy == "N"){
}message("This individual was previously labeled a nomad.")
else if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Strategy == "U"){
}message("This individual was previously labeled unknown.")
}## View current NSD plot
message(paste("Check:",notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Notes))
shell.exec(paste0(getwd(), "/unsorted_output/",herd, "/", yrs[y],"/",individs_list[id], "_graphic.html", sep = ""))
## Resume?
<- readline("Keep current NSD (skip this revisit)? Y or N ")
skip_revisit $Animal_ID == individs_list[id], ]$Revisit <- readline("Revisit another time? Y or N ")
notes_tab[notes_tabif(skip_revisit == "Y"){
fwrite(notes_tab, paste0(getwd(), "/unsorted_output/", herd, "/", yrs[y],
"/", yrs[y], "_overall.csv"), row.names = FALSE,
dateTimeAs = c("write.csv"))
system2("taskkill",args="/im chrome.exe")
next
}
}
# Examine Movements...
repeat{
<- yr_recs[yr_recs$Animal_ID == individs_list[id], ]
id_recs
#Show locs
print({
<- coords_as_sf(id_recs,"WGS84_Long","WGS84_Lat","WGS84")
shp <- maptiles::get_tiles(shp, provider = "Esri.WorldTopoMap", crop=T, zoom=10, cachedir = ".") %>%
tile1 ::project(.,terra::crs(shp))
terra::x11()
grDevicesggplot() +
::geom_spatraster_rgb(data = tile1, maxcell = Inf) +
tidyterrageom_sf(data = shp) +
labs(title = paste0("Animal ID: ",individs_list[id]))
})unlink(paste0(inpath,"/EsriWTM"),recursive = T)
## Step 1: Select Anchor Date
repeat{
<- readline("Use Default Anchor Date (March 1) or reveiw options? Y or N ")
def if(def == "N"){
::render(paste0(scriptdir, "/", "mapbox_anchor.Rmd"),
rmarkdownoutput_file = paste0(individs_list[id], "_anchors.html"),
output_dir = paste0(getwd(), "/unsorted_output/",
"/", yrs[y], sep = ""))
herd, shell.exec(paste0(getwd(), "/unsorted_output/",herd, "/", yrs[y],"/",individs_list[id], "_anchors.html", sep = ""))
repeat{
<- readline("Enter Anchor Date (M-DD) ")
anc_date print(paste("Using Anchor Date ", anc_date))
<- as.POSIXct(strptime(paste0(yrs[y], "-",anc_date," 00:00:00"), format = "%Y-%m-%d %H:%M:%S"),
orig_date origin = "1970-01-01 00:00:00")
<- id_recs[abs(id_recs$GMT - orig_date) ==
orig_date_recs min(abs(id_recs$GMT - orig_date)), ][1, ]
print(paste("NSD calculated from origin at", orig_date_recs$GMT))
year(id_recs$GMT) == yrs[y] , "Root_NSD"] <-
id_recs[year(id_recs$GMT) == yrs[y] , "IDTM_X"] - orig_date_recs$IDTM_X)^2 +
((id_recs[year(id_recs$GMT) == yrs[y] , "IDTM_Y"] - orig_date_recs$IDTM_Y)^2)^0.5
(id_recs[print(ggplot(id_recs,aes(x=GMT,y=Root_NSD)) +
geom_point(color=id_recs$color) + geom_line(color=id_recs$color) +
labs(x="GMT",y="Root_NSD",
title = paste0("Animal ID: ",individs_list[id]),
caption=paste0("Anchor Date: ",format.Date(orig_date,"%B %d"))))
<- readline("NSD and Anchor Date look good? Y or N ")
BR if(BR == "Y"){
break
}
}else{
}# Set date of origin
print("Using Default Anchor Date (March 1).")
<- as.POSIXct(strptime(paste0(yrs[y], "-3-01 00:00:00"), format = "%Y-%m-%d %H:%M:%S"),
orig_date origin = "1970-01-01 00:00:00") # origin date is March 1
<- id_recs[abs(id_recs$GMT - orig_date) ==
orig_date_recs min(abs(id_recs$GMT - orig_date)), ][1, ]
print(paste("NSD calculated from origin at", orig_date_recs$GMT))
}$Animal_ID == individs_list[id], ]$AnchorDate <- format.Date(orig_date,"%B %d")
notes_tab[notes_tabyear(id_recs$GMT) == yrs[y] , "Root_NSD"] <-
id_recs[year(id_recs$GMT) == yrs[y] , "IDTM_X"] - orig_date_recs$IDTM_X)^2 +
((id_recs[year(id_recs$GMT) == yrs[y] , "IDTM_Y"] - orig_date_recs$IDTM_Y)^2)^0.5
(id_recs[print(ggplot(id_recs,aes(x=GMT,y=Root_NSD)) +
geom_point(color=id_recs$color) + geom_line(color=id_recs$color) +
labs(x="GMT",y="Root_NSD",
title = paste0("Animal ID: ",individs_list[id]),
caption=paste0("Anchor Date: ",format.Date(orig_date,"%B %d"))))
<- readline("NSD and Anchor Date look good? Y or N ")
BR if(BR == "Y"){
break
}
}###
# Skip animal or classify migration dates
$Animal_ID == individs_list[id], ]$Skip <- readline("Skip this animal? Y or N ")
notes_tab[notes_tab
## Step 2: Trim or Discard spurious points
if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Skip == "N"){
$Animal_ID == individs_list[id], ]$Trim <- readline("Trim points from the graph? Y or N ")
notes_tab[notes_tabif(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Trim == "Y"){
<- NULL
discard_all repeat{
<- readline("Discard points from the top(T), bottom(B) right(R), or left(L) of graph? T, B, R, or L ")
TR if(TR == "T"){
print("Click below the points to discard.")
<- ggmap::gglocator(n=1,mercator = F)
discard <- id_recs[as.numeric(na.omit(id_recs$Root_NSD)) > discard$Root_NSD, ]
discarded <- id_recs[as.numeric(na.omit(id_recs$Root_NSD)) < discard$Root_NSD, ]
id_recs $Animal_ID == individs_list[id], ]$Trim_type <- ifelse(is.na(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Trim_type),TR,
notes_tab[notes_tabpaste0(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Trim_type,TR))
else if(TR == "R") {
} print("Click left of the points to discard.")
<- ggmap::gglocator(n=1,mercator = F)
discard <- id_recs[as.numeric(na.omit(id_recs$GMT)) > discard$GMT, ]
discarded <- id_recs[as.numeric(na.omit(id_recs$GMT)) < discard$GMT, ]
id_recs $Animal_ID == individs_list[id], ]$Trim_type <- ifelse(is.na(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Trim_type),TR,
notes_tab[notes_tabpaste0(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Trim_type,TR))
else if(TR == "L") {
} print("Click right of the points to discard.")
<- ggmap::gglocator(n=1,mercator = F)
discard <- id_recs[as.numeric(na.omit(id_recs$GMT)) < discard$GMT, ]
discarded <- id_recs[as.numeric(na.omit(id_recs$GMT)) > discard$GMT, ]
id_recs $Animal_ID == individs_list[id], ]$Trim_type <- ifelse(is.na(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Trim_type),TR,
notes_tab[notes_tabpaste0(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Trim_type,TR))
else if(TR == "B") {
} print("Click above the points to discard.")
<- ggmap::gglocator(n=1,mercator = F)
discard <- id_recs[as.numeric(na.omit(id_recs$Root_NSD)) < discard$Root_NSD, ]
discarded <- id_recs[as.numeric(na.omit(id_recs$Root_NSD)) > discard$Root_NSD, ]
id_recs $Animal_ID == individs_list[id], ]$Trim_type <- ifelse(is.na(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Trim_type),TR,
notes_tab[notes_tabpaste0(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Trim_type,TR))
}<- rbind(discard_all,discarded)
discard_all <- readline("Discard more points? Y or N ")
BR if(BR == "N"){
break
}
}
}###
repeat{
print(ggplot(id_recs,aes(x=GMT,y=Root_NSD)) +
geom_point(color=id_recs$color) + geom_line(color=id_recs$color) +
labs(x="GMT",y="Root_NSD",
title = paste0("Animal ID: ",individs_list[id]),
caption=paste0("Anchor Date: ",format.Date(orig_date,"%B %d"))))
$Animal_ID == individs_list[id], ]$Strategy <- readline("Identify tentative migration strategy.
notes_tab[notes_tabPlease list M (migratory), MM(mixed-migratory), R(resident), N(nomadic), or U(unclear) ")
if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Strategy == "R"){
$habitat <- "Resident"
id_recs$Hab_code <- "Resident"
id_recs<- dplyr::left_join(id_recs[,-which(stringr::str_detect(colnames(id_recs),"color")==T)],hab_palette[,c(-1)],by="Hab_code")
id_recs ::render(paste0(scriptdir, "/", "mapbox_plot.Rmd"),
rmarkdownoutput_file = paste0(individs_list[id], "_graphic.html"),
output_dir = paste0(getwd(), "/unsorted_output/",
"/", yrs[y], sep = ""))
herd, shell.exec(paste0(getwd(), "/unsorted_output/",herd, "/", yrs[y],"/",individs_list[id], "_graphic.html", sep = ""))
if(readline("Open the output file. Look good? Y or N ") == "Y"){
break
else{
}$habitat <- "not assigned"
id_recs$color <- "#000000"
id_recs$Hab_code <- NULL
id_recs
}
}if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Strategy == "N"){
$habitat <- "Nomad"
id_recs$Hab_code <- "Nomad"
id_recs<- dplyr::left_join(id_recs[,-which(stringr::str_detect(colnames(id_recs),"color")==T)],hab_palette[,c(-1)],by="Hab_code")
id_recs ::render(paste0(scriptdir, "/", "mapbox_plot.Rmd"),
rmarkdownoutput_file = paste0(individs_list[id], "_graphic.html"),
output_dir = paste0(getwd(), "/unsorted_output/",
"/", yrs[y], sep = ""))
herd,
shell.exec(paste0(getwd(), "/unsorted_output/",herd, "/", yrs[y],"/",individs_list[id], "_graphic.html", sep = ""))
if(readline("Open the output file. Look good? Y or N ") == "Y"){
break
else{
}$habitat <- "not assigned"
id_recs$color <- "#000000"
id_recs$Hab_code <- NULL
id_recs
}
}if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Strategy != "R" &
$Animal_ID == individs_list[id], ]$Strategy != "N"){
notes_tab[notes_tab
## Step 3: Classify Movement Dates
repeat{
# Plot NSD
print(plt <-ggplot(id_recs,aes(x=GMT,y=Root_NSD)) +
geom_point(color=id_recs$color) + geom_line(color=id_recs$color) +
labs(x="GMT",y="Root NSD",title = paste0("Animal ID: ",individs_list[id]))+
theme_bw())
<- readline("What kind of movement is this? Spring(sp), Fall(fa), Winter movement (wm), or Summer movement (sm)? ")
mig
if(mig == "sp"){
print("Select Spring Migration Dates")
repeat{
# Plot NSD
print(
<-ggplot(id_recs,aes(x=GMT,y=Root_NSD)) +
plt geom_point(color=id_recs$color) + geom_line(color=id_recs$color) +
labs(x="GMT",y="Root NSD",title = paste0("Animal ID: ",individs_list[id]))+
theme_bw()
)# Zoom in on dates of spring migration
print("Click the earlier date of the range you'd like to zoom to")
<- ggmap::gglocator(n=1,mercator = F)$GMT
windowstart print(plt + geom_vline(xintercept = windowstart))
print("Click the later date of the range you'd like to zoom to")
<- ggmap::gglocator(n=1,mercator = F)$GMT
windowend <- id_recs[as.numeric(na.omit(id_recs$GMT)) >
window_recs & as.numeric(na.omit(id_recs$GMT)) < windowend, ]
windowstart print(plt <- ggplot(window_recs,aes(x=GMT,y=Root_NSD)) +
geom_point(color=window_recs$color) + geom_line(color=window_recs$color) +
labs(x="GMT",y="Root NSD",title = paste0("Animal ID: ",individs_list[id])))
# Pick start/end dates with locator; assign/paste makes new variables for the loop
print("Click the start of the spring migration")
<- ggmap::gglocator(n=1,mercator = F)$GMT
start print(plt <- plt + geom_vline(xintercept = start, color='limegreen'))
print("Click the end of the spring migration")
<- ggmap::gglocator(n=1,mercator = F)$GMT
end print(plt <- plt + geom_vline(xintercept = end, color='darkred'))
# Identify dates in selected range
<- substr(yrs[y], 3, 4)
year <- as.POSIXct(start, origin = "1970-01-01 00:00:00",tz='GMT')
spring_start <- as.POSIXct(end, origin = "1970-01-01 00:00:00",tz='GMT')
spring_end if(spring_start > orig_date){ #spring identified in current year sequence
$habitat <- ifelse(spring_start <= id_recs$GMT & id_recs$GMT <= spring_end,paste0("sprmig", year),
id_recs$habitat)
id_recselse{#spring identified in last year sequence
}$habitat <- ifelse(spring_start <= id_recs$GMT & id_recs$GMT <= spring_end,paste0("sprmig", (as.numeric(year)-1)),
id_recs$habitat)
id_recs
}$Hab_code <- stringr::str_split_fixed(id_recs$habitat,"[:digit:]",2)[,1]
id_recs<- dplyr::left_join(id_recs[,-which(stringr::str_detect(colnames(id_recs),"color")==T)],hab_palette[,c(-1)],by="Hab_code")
id_recs
# ~~*plotting magic*~~
::render(paste0(scriptdir, "/", "mapbox_plot.Rmd"),
rmarkdownoutput_file = paste0(individs_list[id], "_graphic.html"),
output_dir = paste0(getwd(), "/unsorted_output/",
"/", yrs[y], sep = ""))
herd,
shell.exec(paste0(getwd(), "/unsorted_output/",herd, "/", yrs[y],"/",individs_list[id], "_graphic.html", sep = ""))
if(readline("Open the output file. Look good? Y or N ") == "Y"){
break
else{
}$habitat <- ifelse(spring_start <= id_recs$GMT & id_recs$GMT <= spring_end,"not assigned",
id_recs$habitat)
id_recs$color <- ifelse(spring_start <= id_recs$GMT & id_recs$GMT <= spring_end,"#000000",
id_recs$color)
id_recs$Hab_code <- NULL
id_recs
}
# end of repeat for spring migration dates
}
try({
# Identify the migration start and end dates and distance. Date_times are written in excel format to ensure consistency.
<- spring_start
s_migration_start_date $Animal_ID == individs_list[id], ]$SprMig_Start <-
notes_tab[notes_tabtoString(format(s_migration_start_date, format = "%m/%d/%Y %H:%M:%S"))
<- spring_end
s_migration_end_date $Animal_ID == individs_list[id], ]$SprMig_End <-
notes_tab[notes_tabtoString(format(s_migration_end_date, format = "%m/%d/%Y %H:%M:%S"))
<- id_recs %>%
ss ::filter(abs(difftime(GMT,s_migration_start_date)) == min(abs(difftime(GMT,s_migration_start_date)))) %>%
dplyr::select(IDTM_X,IDTM_Y) %>%
dplyrunique(.)
<- id_recs %>%
se ::filter(abs(difftime(GMT,s_migration_end_date)) == min(abs(difftime(GMT,s_migration_end_date)))) %>%
dplyr::select(IDTM_X,IDTM_Y) %>%
dplyrunique(.)
<- ((ss$IDTM_X - se$IDTM_X)^2 + (ss$IDTM_Y - se$IDTM_Y)^2)^0.5
s_migration_distance
$Animal_ID == individs_list[id], ]$SprMig_Dist <- s_migration_distance
notes_tab[notes_tab
})
}if(mig == "fa"){
print("Select Fall Migration Dates")
repeat{
# Plot NSD
print(
<-ggplot(id_recs,aes(x=GMT,y=Root_NSD)) +
plt geom_point(color=id_recs$color) + geom_line(color=id_recs$color) +
labs(x="GMT",y="Root NSD",title = paste0("Animal ID: ",individs_list[id]))+
theme_bw()
)# Zoom in on dates of spring migration
print("Click the earlier date of the range you'd like to zoom to")
<- ggmap::gglocator(n=1,mercator = F)$GMT
windowstart print(plt + geom_vline(xintercept = windowstart))
print("Click the later date of the range you'd like to zoom to")
<- ggmap::gglocator(n=1,mercator = F)$GMT
windowend <- id_recs[as.numeric(na.omit(id_recs$GMT)) >
window_recs & as.numeric(na.omit(id_recs$GMT)) < windowend, ]
windowstart print(plt <- ggplot(window_recs,aes(x=GMT,y=Root_NSD)) +
geom_point(color=window_recs$color) + geom_line(color=window_recs$color) +
labs(x="GMT",y="Root NSD",title = paste0("Animal ID: ",individs_list[id])))
# Pick start/end dates with locator; assign/paste makes new variables for the loop
print("Click the start of the fall migration")
<- ggmap::gglocator(n=1,mercator = F)$GMT
start print(plt <- plt + geom_vline(xintercept = start, color='limegreen'))
print("Click the end of the fall migration")
<- ggmap::gglocator(n=1,mercator = F)$GMT
end print(plt <- plt + geom_vline(xintercept = end, color='darkred'))
# Identify dates in selected range; identify habitat for dates prior to this range
<- substr(yrs[y], 3, 4)
year <- as.POSIXct(start, origin = "1970-01-01 00:00:00",tz='UTC')
fall_start <- as.POSIXct(end, origin = "1970-01-01 00:00:00",tz='UTC')
fall_end if(fall_start > orig_date){ #spring identified in current year sequence
$habitat <- ifelse(fall_start <= id_recs$GMT & id_recs$GMT <= fall_end,paste0("fallmig", year),
id_recs$habitat)
id_recselse{#spring identified in last year sequence
}$habitat <- ifelse(fall_start <= id_recs$GMT & id_recs$GMT <= fall_end,paste0("fallmig", (as.numeric(year)-1)),
id_recs$habitat)
id_recs
}$Hab_code <- stringr::str_split_fixed(id_recs$habitat,"[:digit:]",2)[,1]
id_recs<- dplyr::left_join(id_recs[,-which(stringr::str_detect(colnames(id_recs),"color")==T)],hab_palette[,c(-1)],by="Hab_code")
id_recs
# ~~*plotting magic*~~
::render(paste0(scriptdir, "/", "mapbox_plot.Rmd"),
rmarkdownoutput_file = paste0(individs_list[id], "_graphic.html"),
output_dir = paste0(getwd(), "/unsorted_output/",
"/", yrs[y], sep = ""))
herd,
shell.exec(paste0(getwd(), "/unsorted_output/",herd, "/", yrs[y],"/",individs_list[id], "_graphic.html", sep = ""))
if(readline("Open the output file. Look good? Y or N ") == "Y"){
break
else{
}$habitat <- ifelse(fall_start <= id_recs$GMT & id_recs$GMT <= fall_end,"not assigned",
id_recs$habitat)
id_recs$color <- ifelse(fall_start <= id_recs$GMT & id_recs$GMT <= fall_end,"#000000",
id_recs$color)
id_recs$Hab_code <- NULL
id_recs
}
# end of repeat for fall migration dates
} try({
if(nrow(id_recs[id_recs$habitat == paste0("fallmig", year), ]) != 0){
# identify the migration start and end dates and distance
<- fall_start
f_migration_start_date $Animal_ID == individs_list[id], ]$FallMig_Start <-
notes_tab[notes_tabtoString(format(f_migration_start_date, format = "%m/%d/%Y %H:%M:%S"))
<- fall_end
f_migration_end_date $Animal_ID == individs_list[id], ]$FallMig_End <-
notes_tab[notes_tabtoString(format(f_migration_end_date, format = "%m/%d/%Y %H:%M:%S"))
<- id_recs %>%
fs ::filter(abs(difftime(GMT,f_migration_start_date)) == min(abs(difftime(GMT,f_migration_start_date)))) %>%
dplyr::select(IDTM_X,IDTM_Y) %>%
dplyrunique(.)
<- id_recs %>%
fe ::filter(abs(difftime(GMT,f_migration_end_date)) == min(abs(difftime(GMT,f_migration_end_date)))) %>%
dplyr::select(IDTM_X,IDTM_Y) %>%
dplyrunique(.)
<- ((fs$IDTM_X - fe$IDTM_X)^2 + (fs$IDTM_Y - fe$IDTM_Y)^2)^0.5
f_migration_distance
$Animal_ID == individs_list[id], ]$FallMig_Dist <- f_migration_distance
notes_tab[notes_tab
}
})
} if(mig == "wm"){
print("Select Winter Movement Dates")
repeat{
# Plot NSD
print(
<-ggplot(id_recs,aes(x=GMT,y=Root_NSD)) +
plt geom_point(color=id_recs$color) + geom_line(color=id_recs$color) +
labs(x="GMT",y="Root NSD",title = paste0("Animal ID: ",individs_list[id]))+
theme_bw()
)# Zoom in on dates of spring migration
print("Click the earlier date of the range you'd like to zoom to")
<- ggmap::gglocator(n=1,mercator = F)$GMT
windowstart print(plt + geom_vline(xintercept = windowstart))
print("Click the later date of the range you'd like to zoom to")
<- ggmap::gglocator(n=1,mercator = F)$GMT
windowend <- id_recs[as.numeric(na.omit(id_recs$GMT)) >
window_recs & as.numeric(na.omit(id_recs$GMT)) < windowend, ]
windowstart print(plt <- ggplot(window_recs,aes(x=GMT,y=Root_NSD)) +
geom_point(color=window_recs$color) + geom_line(color=window_recs$color) +
labs(x="GMT",y="Root NSD",title = paste0("Animal ID: ",individs_list[id])))
# Pick start/end dates with locator; assign/paste makes new variables for the loop
print("Click the start of the winter movement")
<- ggmap::gglocator(n=1,mercator = F)$GMT
start print(plt <- plt + geom_vline(xintercept = start, color='limegreen'))
print("Click the end of the winter movement")
<- ggmap::gglocator(n=1,mercator = F)$GMT
end print(plt <- plt + geom_vline(xintercept = end, color='darkred'))
# Identify dates in selected range; identify habitat for dates prior to this range
<- substr(yrs[y], 3, 4)
year <- as.POSIXct(start, origin = "1970-01-01 00:00:00",tz='UTC')
s <- as.POSIXct(end, origin = "1970-01-01 00:00:00",tz='UTC')
e $habitat <- ifelse(s <= id_recs$GMT & id_recs$GMT <= e,"wntmov",id_recs$habitat)
id_recs$Hab_code <- stringr::str_split_fixed(id_recs$habitat,"[:digit:]",2)[,1]
id_recs<- dplyr::left_join(id_recs[,-which(stringr::str_detect(colnames(id_recs),"color")==T)],hab_palette[,c(-1)],by="Hab_code")
id_recs
# ~~*plotting magic*~~
::render(paste0(scriptdir, "/", "mapbox_plot.Rmd"),
rmarkdownoutput_file = paste0(individs_list[id], "_graphic.html"),
output_dir = paste0(getwd(), "/unsorted_output/",
"/", yrs[y], sep = ""))
herd,
shell.exec(paste0(getwd(), "/unsorted_output/",herd, "/", yrs[y],"/",individs_list[id], "_graphic.html", sep = ""))
if(readline("Open the output file. Look good? Y or N ") == "Y"){
break
else{
}$habitat <- ifelse(s <= id_recs$GMT & id_recs$GMT <= e,"not assigned",
id_recs$habitat)
id_recs$color <- ifelse(s <= id_recs$GMT & id_recs$GMT <= e,"#000000",
id_recs$color)
id_recs$Hab_code <- NULL
id_recs
}
# end of repeat for winter movement dates
}
} if(mig == "sm"){
print("Select Summer Movement Dates")
repeat{
# Plot NSD
print(
<-ggplot(id_recs,aes(x=GMT,y=Root_NSD)) +
plt geom_point(color=id_recs$color) + geom_line(color=id_recs$color) +
labs(x="GMT",y="Root NSD",title = paste0("Animal ID: ",individs_list[id]))+
theme_bw()
)# Zoom in on dates of spring migration
print("Click the earlier date of the range you'd like to zoom to")
<- ggmap::gglocator(n=1,mercator = F)$GMT
windowstart print(plt + geom_vline(xintercept = windowstart))
print("Click the later date of the range you'd like to zoom to")
<- ggmap::gglocator(n=1,mercator = F)$GMT
windowend <- id_recs[as.numeric(na.omit(id_recs$GMT)) >
window_recs & as.numeric(na.omit(id_recs$GMT)) < windowend, ]
windowstart print(plt <- ggplot(window_recs,aes(x=GMT,y=Root_NSD)) +
geom_point(color=window_recs$color) + geom_line(color=window_recs$color) +
labs(x="GMT",y="Root NSD",title = paste0("Animal ID: ",individs_list[id])))
# Pick start/end dates with locator; assign/paste makes new variables for the loop
print("Click the start of the summer movement")
<- ggmap::gglocator(n=1,mercator = F)$GMT
start print(plt <- plt + geom_vline(xintercept = start, color='limegreen'))
print("Click the end of the summer movement")
<- ggmap::gglocator(n=1,mercator = F)$GMT
end print(plt <- plt + geom_vline(xintercept = end, color='darkred'))
# Identify dates in selected range; identify habitat for dates prior to this range
<- substr(yrs[y], 3, 4)
year <- as.POSIXct(start, origin = "1970-01-01 00:00:00",tz='UTC')
s <- as.POSIXct(end, origin = "1970-01-01 00:00:00",tz='UTC')
e $habitat <- ifelse(s <= id_recs$GMT & id_recs$GMT <= e,"summov",id_recs$habitat)
id_recs$Hab_code <- stringr::str_split_fixed(id_recs$habitat,"[:digit:]",2)[,1]
id_recs<- dplyr::left_join(id_recs[,-which(stringr::str_detect(colnames(id_recs),"color")==T)],hab_palette[,c(-1)],by="Hab_code")
id_recs
# ~~*plotting magic*~~
::render(paste0(scriptdir, "/", "mapbox_plot.Rmd"),
rmarkdownoutput_file = paste0(individs_list[id], "_graphic.html"),
output_dir = paste0(getwd(), "/unsorted_output/",
"/", yrs[y], sep = ""))
herd,
shell.exec(paste0(getwd(), "/unsorted_output/",herd, "/", yrs[y],"/",individs_list[id], "_graphic.html", sep = ""))
if(readline("Open the output file. Look good? Y or N ") == "Y"){
break
else{
}$habitat <- ifelse(s <= id_recs$GMT & id_recs$GMT <= e,"not assigned",
id_recs$habitat)
id_recs$color <- ifelse(s <= id_recs$GMT & id_recs$GMT <= e,"#000000",
id_recs$color)
id_recs$Hab_code <- NULL
id_recs
}
# end of repeat for summer movement dates
}
}<- readline("Classify more movements? Y or N ")
BR if(BR == "N"){
$Animal_ID == individs_list[id], ]$Strategy <- readline("Identify final migration strategy.
notes_tab[notes_tabPlease list M (migratory), MM(mixed-migratory), or U(unclear) ")
break
}# end of repeat for migration date classifications
} # end of Date Selection
} ::render(paste0(scriptdir, "/", "mapbox_plot.Rmd"),
rmarkdownoutput_file = paste0(individs_list[id], "_graphic.html"),
output_dir = paste0(getwd(), "/unsorted_output/",
"/", yrs[y], sep = ""))
herd,
shell.exec(paste0(getwd(), "/unsorted_output/",herd, "/", yrs[y],"/",individs_list[id], "_graphic.html", sep = ""))
if(readline("Open the output file. Look good? Y or N ") == "Y"){break}
#classify repeat
} # Finish Classifying Dates
if(exists("discard_all")){
$habitat <- "Discard"
discard_all$Hab_code <- "Discard"
discard_all<- dplyr::left_join(discard_all[,-which(stringr::str_detect(colnames(discard_all),"color")==T)],hab_palette[,c(-1)],by="Hab_code")
discard_all <- id_recs %>%
id_recs rbind(.,discard_all) %>%
::arrange(.,GMT)
dplyrrm(discard_all,discard,discarded)
}<- classify_dates(id_recs)
id_recs
#~~*plotting magic*~~
::render(paste0(scriptdir, "/", "mapbox_plot.Rmd"),
rmarkdownoutput_file = paste0(individs_list[id], "_graphic.html"),
output_dir = paste0(getwd(), "/unsorted_output/",
"/", yrs[y], sep = ""))
herd,
shell.exec(paste0(getwd(), "/unsorted_output/",herd, "/", yrs[y],"/",individs_list[id], "_graphic.html", sep = ""))
if(readline("Look good? Y or N ") == "Y"){break}
}if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Skip == "Y"){break}
# end of repeat for individual
}
$Animal_ID == individs_list[id], ]$Revisit <- readline("Revisit this animal later? Y or N ")
notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Notes <- readline("Write whatever notes you want ")
notes_tab[notes_tab
# Paste labels onto the graphics
if(notes_tab[notes_tab$Animal_ID == individs_list[id], ]$Skip == "Y"){
$habitat <- "not assigned"
id_recs$Animal_ID == individs_list[id], !names(notes_tab) %in% c("Skip", "Months_of_Data", "Animal_ID", "Notes","Region","AnchorDate","Revisit")] <- NA # ; wipe out any data created for this animal, b/c skipping it now
notes_tab[notes_tab
}
# Flag Migrations that might be too short (less than 5 km)
$Animal_ID == individs_list[id],]$FlagMig <- ifelse(is.na(notes_tab[notes_tab$Animal_ID == individs_list[id],]$SprMig_Dist)==T & is.na(notes_tab[notes_tab$Animal_ID == individs_list[id],]$FallMig_Dist)==T, F,
notes_tab[notes_tabifelse(is.na(notes_tab[notes_tab$Animal_ID == individs_list[id],]$FallMig_Dist)==T & is.na(notes_tab[notes_tab$Animal_ID == individs_list[id],]$SprMig_Dist)==F & notes_tab[notes_tab$Animal_ID == individs_list[id],]$SprMig_Dist <= 5000, T,
ifelse(is.na(notes_tab[notes_tab$Animal_ID == individs_list[id],]$FallMig_Dist)==F & is.na(notes_tab[notes_tab$Animal_ID == individs_list[id],]$SprMig_Dist)==T & notes_tab[notes_tab$Animal_ID == individs_list[id],]$FallMig_Dist <= 5000, T,
ifelse(notes_tab[notes_tab$Animal_ID == individs_list[id],]$FallMig_Dist <= 5000 | notes_tab[notes_tab$Animal_ID == individs_list[id],]$SprMig_Dist <= 5000, T, F))))
print("Finalizing output graphics.")
<- id_recs[year(id_recs$GMT) == yrs[y], ] # redefine id_records, now that id_recs is classified
id_recs ::render(paste0(scriptdir, "/", "mapbox_plot.Rmd"),
rmarkdownoutput_file = paste0(individs_list[id], "_graphic.html"),
output_dir = paste0(getwd(), "/unsorted_output/", herd,
"/", yrs[y], sep = ""))
print("Writing output tables.")
fwrite(id_recs, paste0(getwd(), "/unsorted_output/", herd, "/", yrs[y],
"/", individs_list[id], ".csv"), row.names = FALSE,
dateTimeAs = c("write.csv"))
fwrite(notes_tab, paste0(getwd(), "/unsorted_output/", herd, "/", yrs[y],
"/", yrs[y], "_overall.csv"), row.names = FALSE,
dateTimeAs = c("write.csv"))
print("Updating overall table with new values.")
<- all_recs %>%
all_recs ::anti_join(.,id_recs[,-which(stringr::str_detect(colnames(id_recs),"color|habitat|Hab_code")==T)],by=c("Animal_ID","GMT")) %>%
dplyrrbind(.,id_recs[,-which(stringr::str_detect(colnames(id_recs),"Hab_code")==T)]) %>%
::arrange(.,Animal_ID,GMT)
dplyr
<- savecounter + 1
savecounter if(savecounter == 5){
print("5 animals done. Backing up the data table.")
fwrite(all_recs, outfile, row.names = FALSE, dateTimeAs = c("write.csv"))
<- 0
savecounter else if (readline("Save manually? Do this if you are exiting the script. Y or N ") == "Y") {
} fwrite(all_recs, outfile, row.names = FALSE, dateTimeAs = c("write.csv"))
<- 0
savecounter else {
} print(paste("Overall file will back up automatically after", 5 - savecounter, "more animals"))
} ::dev.off()
grDevicessystem2("taskkill",args="/im chrome.exe")
# individual loop
}
# year loop }
Migrations
I am currently an Associate Research Scientist for the Wyoming Cooperative Fish and Wildlife Research Unit modeling ungulate seasonal ranges and migrations for Idaho Department of Fish and Game in support of S.O. 3362. One of my primary duties is to classify migrations of Idaho’s mule deer, elk, and pronghorn using net-squared displacement analysis. I also maintain and enhance the analysis code to streamline the workflow and allow for flexibility to accommodate complex migration patterns.