|
1 |
| -#### Functions for data processing spatial BBJ method #### |
2 |
| - |
3 |
| -#### Set reliability vector, PO (base) is default #### |
4 |
| -set.rel <- function(d, rel="A") { |
5 |
| - d <- d[,-c(4,7,10:16)] |
6 |
| - d$prob <- NA |
7 |
| - |
8 |
| - # Ratings: P = 3-5, S = 2-5, O = 1-5, I = 1-5 with: max(thyly[which(thyly$edec=="O"),8]) |
9 |
| - # For es, 5 keeps set rating, 4-1 cause fixed or proportional (multiplier) decreases |
10 |
| - # Reference reductions: 5=5/5=1, 4=4/5=0.8, 3=3/5=0.6, 2=2/5=0.4, 1=1/5=0.2 |
11 |
| - p.div <- 5 |
12 |
| - e.div <- 5 |
13 |
| - o.div <- 5 |
14 |
| - # incr or decr if want rating multiplier to be shallower or steeper, e.g. 4 gives 1,1,0.75,0.5,0.25 |
15 |
| - pr <- switch(rel, |
16 |
| - # Probabilities assigned to each type: |
17 |
| - # PS EO EI OO OI |
18 |
| - "P"= c(1, 0.00, 0.0, 0.00, 0.00), |
19 |
| - "EH"=c(1, 0.50, 0.2, 0.00, 0.00), |
20 |
| - "EO"=c(0, 0.25, 0.1, 0.00, 0.00), |
21 |
| - "E"= c(1, 0.25, 0.1, 0.00, 0.00), |
22 |
| - "A"= c(1, 0.25, 0.1, 0.05, 0.01), |
23 |
| - "XA"=c(1, 0.05, 0.01, 0.005, 0.001), |
24 |
| - "S5"=c(1, 0.1, 0, 0, 0)) |
25 |
| - # P = physical records only, EH = physical/expert high, E = physical/expert default, A = all record types included |
26 |
| - |
27 |
| - d[d$edec=="PS","prob"] <- pmin(1,pr[1]*(d[d$edec=="PS","rating"]/p.div)) |
28 |
| - d[d$edec=="EO","prob"] <- pmin(1,pr[2]*(d[d$edec=="EO","rating"]/e.div)) |
29 |
| - d[d$edec=="EI","prob"] <- pmin(1,pr[3]*(d[d$edec=="EI","rating"]/e.div)) |
30 |
| - d[d$edec=="OO","prob"] <- pmin(1,pr[4]*(d[d$edec=="OO","rating"]/o.div)) |
31 |
| - d[d$edec=="OI","prob"] <- pmin(1,pr[5]*(d[d$edec=="OI","rating"]/o.div)) |
32 |
| - return(d) |
33 |
| -} |
34 |
| - |
35 |
| -#### Combine repeated sightings in a year and return dataframe #### |
36 |
| -dmy.cprob <- function(dd,plot=T) { |
37 |
| - dd <- dd[order(dd$year),] # ensure data is ordered by year |
38 |
| - for(i in unique(dd$year)) { |
39 |
| - row.sel <- which(dd$year==i) |
40 |
| - if(length(row.sel) > 1) { |
41 |
| - dd$prob[row.sel[1]] <- 1-prod(1-dd[row.sel,"prob"]) # calculate combined probability for the year |
42 |
| - dd <- dd[-row.sel[-1],] # eliminate all but the first row for each year |
43 |
| - } |
44 |
| - } |
45 |
| - # Tablulate cumulative combinatorial prob. by year, versus last confirmed sighting (similar to model 0) |
46 |
| - dd$cum.prob <- NA |
47 |
| - for(i in 1:length(dd$prob)) { |
48 |
| - dd$cum.prob[i] <- round(1-prod(1-dd$prob[i:length(dd$prob)]),3) |
49 |
| - } # calculate the cumulative probability of persistence, from last 'confirmed' year to last observation |
50 |
| - MTE <- ifelse(max(dd$cum.prob<=0.5),dd$year[min(which(dd$cum.prob<=0.5))],NA) # estimate median TE based on cum.prob |
51 |
| - |
52 |
| - if(plot==T) { |
53 |
| - plot(dd$cum.prob~dd$year, main="Prob. Persistence based on uncertain records",ylim=c(0,1), |
54 |
| - xlab="Year",ylab="cumulative probability") |
55 |
| - lines(dd$year,dd$cum.prob); abline(v=c(min(dd$year),max(dd$year)),col="blue",lty=2); abline(v=MTE,col="red",lty=1) |
56 |
| - print(dd); print(paste("MTE =",MTE)) |
57 |
| - } # Plot the annual vector of combinatorial probabilities |
58 |
| - |
59 |
| - return(dd) |
60 |
| -} |
61 |
| - |
62 |
| -#### Define distance-decay function #### |
63 |
| -tr.exp.decay <- function(a=2, b=1, d=10) min(1, a*b^-d) |
64 |
| - |
65 |
| -#### Set objective function to minimize deviation from required distance-frequency relationship #### |
66 |
| -objective <- function(params) { |
67 |
| - |
68 |
| - ted.opt <- function(a, b, x, f) { |
69 |
| - pr.freq <- sapply(x, tr.exp.decay, a=a, b=b) |
70 |
| - return(sum((f - pr.freq)^2)) |
71 |
| - } |
72 |
| - |
73 |
| - a <- params[1] |
74 |
| - b <- params[2] |
75 |
| - return(ted.opt(a, b, d, rf)) |
76 |
| -} |
77 |
| - |
78 |
| -#### EDE functions for BBJ18 Method, returning TE (additions here) #### |
79 |
| -so93 <- function(ts) { |
80 |
| - sr <- ts-ts[1]; n <- length(sr)-1 |
81 |
| - return(ts[1]+(n+1)/n*sr[n+1]) |
82 |
| -} # Solow 1993 (+ Strauss & Sadler 1989), returning TE |
83 |
| - |
84 |
| -mc06 <- function(ts) { |
85 |
| - sr <- ts-ts[1]; n <- length(sr)-1 |
86 |
| - return(ts[1]+ceiling(sr[n+1]+log(0.5,1-(n/sr[n+1])))) |
87 |
| -} # McInerney et al. 2006, returning TE |
88 |
| - |
89 |
| -#### Jaric & Roberts 2014 method applied to McInerney 2006, Solow 1993 EDE, or LAD #### |
90 |
| -jr.2014 <- function(dd,ey=2018,a=0.05,m="LAD") { |
91 |
| - |
92 |
| - ts <- dd$year-dd$year[1]; rs <- dd$prob; n <- length(ts) # initialise vars |
93 |
| - tf <- ts[1]*rs[1] # Note: if prob(rs[1]) = 1 then tf==ts[1] |
94 |
| - for(i in n:2) tf <- tf + ts[i]*rs[i]*prod(1-rs[(i-1):1]) |
95 |
| - t0 <- tf+dd$year[1] # most likely first sighting year, in original units |
96 |
| - |
97 |
| - ts <- ts[-min(which(rs>0))]; rs <- rs[-min(which(rs>0))]; n <- n-1 |
98 |
| - tl <- ts[n]*rs[n] # Note: if prob(t.n) = 1 then tl==t.n |
99 |
| - for(i in 1:(n-1)) tl <- tl + ts[i]*rs[i]*prod(1-rs[(i+1):n]) |
100 |
| - |
101 |
| - tr <- tl-tf # most likely sighting period |
102 |
| - r <- sum(rs) # most likely number of observations |
103 |
| - To <- ey-t0 # most likley total observation period |
104 |
| - |
105 |
| - switch(m, |
106 |
| - "so93"={mod <- "Solow 1993"; MTE <- (r+1)/r*tr |
107 |
| - UCI <- tr/(a^(1/r)); p <- (tr/To)^r}, |
108 |
| - "mc06"={mod <- "McInerney et al. 06"; MTE <- ceiling(tr+log(0.5,1-(r/tr))) |
109 |
| - UCI <- ceiling(tr+log(a,1-(r/tr))); p <- (1-(r/tr))^(To-tr)}, |
110 |
| - {mod <- "Most likely endpoint (LAD)"; MTE <- tr; UCI <- NA; p <- NA}) |
111 |
| - |
112 |
| - return(list(Method=mod, MTE=round(t0+MTE), |
113 |
| - UCI=ifelse(is.na(UCI),NA,round(t0+UCI)), p=p)) |
114 |
| -} |
115 |
| - |
116 |
| -#### Return the TE of a grid call in a spatial map #### |
117 |
| -te.grid <- function(x, ts, grd, a=2.15, b=1.074, p=0.01, ede="mc06", result="MTE"){ |
118 |
| - r <- ifelse(result=="UCI",3,2) # report MTE (default) or UCI |
119 |
| - ts$v <- spDistsN1(as.matrix(ts[,c(5,4)]),as.matrix(grd[x,1:2]), longlat=TRUE) # dist of records from grid cell |
120 |
| - ts$v <- pmin(1,a*b^-ts$v) # 1 for all distances up to 10 km, declining expon to 0.01 at 75 km (for default parameters) |
121 |
| - ts <- ts[which(ts$v>p),] # truncate all records further than d km (~75 km for default parameters) |
122 |
| - te <- jr.2014(dmy.cprob(data.frame(year=ts$year,prob=ts$prob*ts$v),plot=F),ey=obs.year,m=ede)[[r]] # LAD, so93 or mc06 |
123 |
| - te <- ifelse(length(te)>0,te,NA) # to avoid crashing if NA value returned by jr.2014 |
124 |
| - return(te) |
125 |
| -} |
| 1 | +#### Functions for data processing spatial BBJ method #### |
| 2 | + |
| 3 | +#### Set reliability vector, PO (base) is default #### |
| 4 | +set.rel <- function(d, rel="A") { |
| 5 | + d <- d[,-c(4,7,10:16)] |
| 6 | + d$prob <- NA |
| 7 | + |
| 8 | + # Ratings: P = 3-5, S = 2-5, O = 1-5, I = 1-5 with: max(thyly[which(thyly$edec=="O"),8]) |
| 9 | + # For es, 5 keeps set rating, 4-1 cause fixed or proportional (multiplier) decreases |
| 10 | + # Reference reductions: 5=5/5=1, 4=4/5=0.8, 3=3/5=0.6, 2=2/5=0.4, 1=1/5=0.2 |
| 11 | + p.div <- 5 |
| 12 | + e.div <- 5 |
| 13 | + o.div <- 5 |
| 14 | + # incr or decr if want rating multiplier to be shallower or steeper, e.g. 4 gives 1,1,0.75,0.5,0.25 |
| 15 | + pr <- switch(rel, |
| 16 | + # Probabilities assigned to each type: |
| 17 | + # PS EO EI OO OI |
| 18 | + "P"= c(1, 0.00, 0.0, 0.00, 0.00), |
| 19 | + "EH"=c(1, 0.50, 0.2, 0.00, 0.00), |
| 20 | + "EO"=c(0, 0.25, 0.1, 0.00, 0.00), |
| 21 | + "E"= c(1, 0.25, 0.1, 0.00, 0.00), |
| 22 | + "A"= c(1, 0.25, 0.1, 0.05, 0.01), |
| 23 | + "XA"=c(1, 0.05, 0.01, 0.005, 0.001), |
| 24 | + "S5"=c(1, 0.1, 0, 0, 0)) |
| 25 | + # P = physical records only, EH = physical/expert high, E = physical/expert default, A = all record types included |
| 26 | + |
| 27 | + d[d$edec=="PS","prob"] <- pmin(1,pr[1]*(d[d$edec=="PS","rating"]/p.div)) |
| 28 | + d[d$edec=="EO","prob"] <- pmin(1,pr[2]*(d[d$edec=="EO","rating"]/e.div)) |
| 29 | + d[d$edec=="EI","prob"] <- pmin(1,pr[3]*(d[d$edec=="EI","rating"]/e.div)) |
| 30 | + d[d$edec=="OO","prob"] <- pmin(1,pr[4]*(d[d$edec=="OO","rating"]/o.div)) |
| 31 | + d[d$edec=="OI","prob"] <- pmin(1,pr[5]*(d[d$edec=="OI","rating"]/o.div)) |
| 32 | + return(d) |
| 33 | +} |
| 34 | + |
| 35 | +#### Combine repeated sightings in a year and return dataframe #### |
| 36 | +dmy.cprob <- function(dd,plot=T) { |
| 37 | + dd <- dd[order(dd$year),] # ensure data is ordered by year |
| 38 | + for(i in unique(dd$year)) { |
| 39 | + row.sel <- which(dd$year==i) |
| 40 | + if(length(row.sel) > 1) { |
| 41 | + dd$prob[row.sel[1]] <- 1-prod(1-dd[row.sel,"prob"]) # calculate combined probability for the year |
| 42 | + dd <- dd[-row.sel[-1],] # eliminate all but the first row for each year |
| 43 | + } |
| 44 | + } |
| 45 | + # Tablulate cumulative combinatorial prob. by year, versus last confirmed sighting (similar to model 0) |
| 46 | + dd$cum.prob <- NA |
| 47 | + for(i in 1:length(dd$prob)) { |
| 48 | + dd$cum.prob[i] <- round(1-prod(1-dd$prob[i:length(dd$prob)]),3) |
| 49 | + } # calculate the cumulative probability of persistence, from last 'confirmed' year to last observation |
| 50 | + MTE <- ifelse(max(dd$cum.prob<=0.5),dd$year[min(which(dd$cum.prob<=0.5))],NA) # estimate median TE based on cum.prob |
| 51 | + |
| 52 | + if(plot==T) { |
| 53 | + plot(dd$cum.prob~dd$year, main="Prob. Persistence based on uncertain records",ylim=c(0,1), |
| 54 | + xlab="Year",ylab="cumulative probability") |
| 55 | + lines(dd$year,dd$cum.prob); abline(v=c(min(dd$year),max(dd$year)),col="blue",lty=2); abline(v=MTE,col="red",lty=1) |
| 56 | + print(dd); print(paste("MTE =",MTE)) |
| 57 | + } # Plot the annual vector of combinatorial probabilities |
| 58 | + |
| 59 | + return(dd) |
| 60 | +} |
| 61 | + |
| 62 | +#### Define distance-decay function #### |
| 63 | +tr.exp.decay <- function(a=2, b=1, d=10) min(1, a*b^-d) |
| 64 | + |
| 65 | +#### Set objective function to minimize deviation from required distance-frequency relationship #### |
| 66 | +objective <- function(params) { |
| 67 | + |
| 68 | + ted.opt <- function(a, b, x, f) { |
| 69 | + pr.freq <- sapply(x, tr.exp.decay, a=a, b=b) |
| 70 | + return(sum((f - pr.freq)^2)) |
| 71 | + } |
| 72 | + |
| 73 | + a <- params[1] |
| 74 | + b <- params[2] |
| 75 | + return(ted.opt(a, b, d, rf)) |
| 76 | +} |
| 77 | + |
| 78 | +#### EDE functions for BBJ18 Method, returning TE (additions here) #### |
| 79 | +so93 <- function(ts) { |
| 80 | + sr <- ts-ts[1]; n <- length(sr)-1 |
| 81 | + return(ts[1]+(n+1)/n*sr[n+1]) |
| 82 | +} # Solow 1993 (+ Strauss & Sadler 1989), returning TE |
| 83 | + |
| 84 | +mc06 <- function(ts) { |
| 85 | + sr <- ts-ts[1]; n <- length(sr)-1 |
| 86 | + return(ts[1]+ceiling(sr[n+1]+log(0.5,1-(n/sr[n+1])))) |
| 87 | +} # McInerney et al. 2006, returning TE |
| 88 | + |
| 89 | +#### Jaric & Roberts 2014 method applied to McInerney 2006, Solow 1993 EDE, or LAD #### |
| 90 | +jr.2014 <- function(dd,ey=2018,a=0.05,m="LAD") { |
| 91 | + |
| 92 | + ts <- dd$year-dd$year[1]; rs <- dd$prob; n <- length(ts) # initialise vars |
| 93 | + tf <- ts[1]*rs[1] # Note: if prob(rs[1]) = 1 then tf==ts[1] |
| 94 | + for(i in n:2) tf <- tf + ts[i]*rs[i]*prod(1-rs[(i-1):1]) |
| 95 | + t0 <- tf+dd$year[1] # most likely first sighting year, in original units |
| 96 | + |
| 97 | + ts <- ts[-min(which(rs>0))]; rs <- rs[-min(which(rs>0))]; n <- n-1 |
| 98 | + tl <- ts[n]*rs[n] # Note: if prob(t.n) = 1 then tl==t.n |
| 99 | + for(i in 1:(n-1)) tl <- tl + ts[i]*rs[i]*prod(1-rs[(i+1):n]) |
| 100 | + |
| 101 | + tr <- tl-tf # most likely sighting period |
| 102 | + r <- sum(rs) # most likely number of observations |
| 103 | + To <- ey-t0 # most likley total observation period |
| 104 | + |
| 105 | + switch(m, |
| 106 | + "so93"={mod <- "Solow 1993"; MTE <- (r+1)/r*tr |
| 107 | + UCI <- tr/(a^(1/r)); p <- (tr/To)^r}, |
| 108 | + "mc06"={mod <- "McInerney et al. 06"; MTE <- ceiling(tr+log(0.5,1-(r/tr))) |
| 109 | + UCI <- ceiling(tr+log(a,1-(r/tr))); p <- (1-(r/tr))^(To-tr)}, |
| 110 | + {mod <- "Most likely endpoint (LAD)"; MTE <- tr; UCI <- NA; p <- NA}) |
| 111 | + |
| 112 | + return(list(Method=mod, MTE=round(t0+MTE), |
| 113 | + UCI=ifelse(is.na(UCI),NA,round(t0+UCI)), p=p)) |
| 114 | +} |
| 115 | + |
| 116 | +#### Return the TE of a grid call in a spatial map #### |
| 117 | +te.grid <- function(x, ts, grd, a=2.15, b=1.074, p=0.01, ede="mc06", result="MTE"){ |
| 118 | + r <- ifelse(result=="UCI",3,2) # report MTE (default) or UCI |
| 119 | + ts$v <- spDistsN1(as.matrix(ts[,c(5,4)]),as.matrix(grd[x,1:2]), longlat=TRUE) # dist of records from grid cell |
| 120 | + ts$v <- pmin(1,a*b^-ts$v) # 1 for all distances up to 10 km, declining expon to 0.01 at 75 km (for default parameters) |
| 121 | + ts <- ts[which(ts$v>p),] # truncate all records further than d km (~75 km for default parameters) |
| 122 | + te <- jr.2014(dmy.cprob(data.frame(year=ts$year,prob=ts$prob*ts$v),plot=F),ey=obs.year,m=ede)[[r]] # LAD, so93 or mc06 |
| 123 | + te <- ifelse(length(te)>0,te,NA) # to avoid crashing if NA value returned by jr.2014 |
| 124 | + return(te) |
| 125 | +} |
0 commit comments