R/simMoveData.R

#Simulate some movement data

#' A function to simulate movement data
#'
#' This function allows you to simulate movement data, where an individual animal is influenced by an external influence. The strength of this influence can be set by the user.
#' @param nobs number of observations. Defaults to 1000.
#' @param ntracks number of observed movement tracks. Defaults to 10.
#' @param meanStepLength mean of step lengths from a lognormal distribution. Defaults to 2.
#' @param sdStepLength sd of step lengths from a lognormal distribution. Defaults to 0.25.
#' @param influenceRange range in which influence point is randomly assigned. Defaults to 50.
#' @param EffectStrength strength of influence relative to directional persistance. Defaults to 0.5.
#' @param bearingSD magnitude of error in directional persistance. Defaults to 5.
#' @keywords simulation, movement
#' @import circular
#' @export
#' @examples
#' simulateData()
#'
#'
simulateData <- function(nobs=1000, ntracks=10, meanStepLength=2, sdStepLength=0.25, influenceRange=50, EffectStrength=0.5, bearingSD=5){

  ####################
  # 1.) Set parameters
  ####################

  #Observations
  N <- nobs                       #number of observations
  J <- 1                          #number of individuals sampled
  K <- ntracks                    #number of observations per track
  tracksPerIndividual <- N/(J*K)  #number of tracks per individual

  #define step length distribution
  meanStepLength <- meanStepLength
  sdStepLength <- sdStepLength

  #For each track this randomly places an influence point on the landscape)
  DWGCrange = influenceRange

  #define beta parameters (effect)
  b_p = 1
  b_f = EffectStrength
  b_m = 0

  #uncertainty (error) around observed angle of travel
  kappa_move = bearingSD #larger number lower uncertanty

  #define individual variation around beta parameters (i.e., individuals respond differently to influences)
  ind_f <- rnorm(J,0,0.0)
  ind_m <- rnorm(J,0,0.0)

  #could add a distance beyond which the influence does not play a role...
  #maxDist = 10


  ####################
  # 2.) Generate data
  ####################

  simData <- data.frame()
  trackCount=1

  for(i in 1:J){  #for each individual

    for(l in 1:tracksPerIndividual){ #for each track

      ##generate static influence points for alternative influencing factors (only two for now, and fixed with a track)
      f.x <- runif(n=1,min=-DWGCrange,max=DWGCrange)
      f.y <- runif(n=1,min=-DWGCrange,max=DWGCrange)
      m.x <- runif(n=1,min=-DWGCrange,max=DWGCrange)
      m.y <- runif(n=1,min=-DWGCrange,max=DWGCrange)

      ##individual always starts one step off of 0,0 moving in a random direction
      obs.x = 0
      obs.y = 0
      angle.p <- rvonmises(1,0,0.01)
      initialStepL <- rlnorm(n=1,meanStepLength,sdStepLength)
      stepL.p <- initialStepL
      obs.x <- obs.x + initialStepL * cos(angle.p) #this is the starting position
      obs.y <- obs.y + initialStepL * sin(angle.p) #this is the starting position

      for(t in 1:K){ #for each observation within a track

        #calculate angles to DWCG
        angle.f <- atan2(f.y-obs.y,f.x-obs.x)
        angle.m <- atan2(m.y-obs.y,m.x-obs.x)

        #calculate distance to DWCG
        dist.f <- (((f.y-obs.y)^2)+((f.x-obs.x)^2))^0.5
        dist.m <- (((m.y-obs.y)^2)+((m.x-obs.x)^2))^0.5

        #calculate next angle of travel based on beta values
        mean_angle <- atan2(b_p*sin(angle.p)+(b_f+ind_f[i])*sin(angle.f)+(b_m+ind_f[i])*sin(angle.m), b_p*cos(angle.p)+(b_f+ind_f[i])*cos(angle.f)+(b_m+ind_m[i])*cos(angle.m))

        #calculate observed angle of travel (mean + uncertainty)
        obs_angle <- rvonmises(1,mean_angle,kappa_move)
        if(obs_angle>pi)obs_angle=obs_angle-2*pi #keep the scale as -pi to +pi to match atan2

        #calculate step length
        stepL <- rlnorm(n=1,meanStepLength,sdStepLength)

        #record one row (one observation)
        simData <- rbind(simData, c(obs_angle, angle.f, angle.m, angle.p, stepL, stepL.p, dist.f, dist.m,i,trackCount,obs.x,obs.y))

        #update new previous angle/step
        angle.p = obs_angle   #this is the previous angle for the next point in the track
        stepL.p = stepL

        #update new position
        obs.x <- obs.x + stepL * cos(obs_angle) #this is the next starting position in the track
        obs.y <- obs.y + stepL * sin(obs_angle) #this is the next starting position in the track

      }
      trackCount=trackCount+1
    }
  }

  names(simData)<-c("obs_angle", "angle.f", "angle.m", "angle.p","stepL","stepL.p", "dist.f", "dist.m","ID","track","x","y")
  return (simData)
}


#' A function to plot the simulated data
#'
#' This function is just a convient way to plot the simulated data.
#' @param simData data generated by simulateData.
#' @param max.tracks limits the plots to tracks below this number.
#' @import ggplot2
#' @export
#' @examples
#' sim.df <- simulateData()
#' simData.plot(sim.df)
#'
#'

simData.plot <- function(simData, max.tracks=5){

  sub.data <- subset(simData,simData$track<=max.tracks)
  ggplot(sub.data, aes(x,y))+geom_point()+geom_path()+facet_grid(. ~ factor(track))

}
tbonne/moveStan documentation built on May 31, 2019, 4:49 a.m.