OSCR

Integrating fossil data in ecological niche models to improve predictions of future habitat of Caribbean corals.

Code ↔ Paper

2 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 2 matches
  1. [1] § METHODS › Ecological niche models ↔ COBI-40-e70323-s014.R, lines 181–239 · score 0.77 · feature classes, cross validation, response curves, binary, sensitivity, likelihood
  2. [2] § METHODS › Environmental data ↔ COBI-40-e70323-s014.R, lines 1415–1428 · score 0.52 · arc minute, Paleo, cell

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

R · 4,467 lines · 195 KB · no license · 2 matches

  1. # reading in packages required
  2. #### line 34-78
  3. # functions
  4. #### line 82-1430
  5. # making master occurrence files- pres = present holo = holocene
  6. #### acer pres master line 1433
  7. #### acer holo master line 1631
  8. #### apal pres master line 1631
  9. #### apal holo master line 1858
  10. #### cnat pres master line 1861
  11. #### cnat holo master line 2057
  12. #### past pres master line 2061
  13. #### past holo master line 2280
  14. # ecospat line #-#
  15. #### acer ecospat line 2293
  16. #### apal ecospat line 2550
  17. #### cnat ecospat line 2805
  18. #### past ecospat line 3079
  19. #ecological niche models pres = present holo = holocene
  20. #### acer pres ENM line 3390
  21. #### acer holo ENM line 3613
  22. #### apal pres ENM line 3868
  23. #### apal holo ENM line 4105
  24. #### cnat pres ENM line 4338
  25. #### cnat holo ENM line 4593
  26. #### past pres ENM line 4849
  27. #### past holo ENM line 5113
  28. ############ plotting by area and latitude
  29. ### latitude line 5365
  30. #################&&&&&&&&&&&&&&&&&&&&&##############Reading in packages
  31. # loading the requisite libraries for generating the master.background and master.occurrence files
  32. library(raster)
  33. library(dplyr)
  34. #ecospat packages
  35. library(ENMTools)
  36. library(dismo)
  37. library(raster)
  38. library(rgdal) # for spatial data analysis
  39. library(dplyr)
  40. library(rgeos) # for spatial data analysis
  41. library(scales)
  42. library(tidyr)
  43. library(colorRamps)
  44. library(ENMeval) # for a few new tools in ENM/SDM
  45. library(ggplot2)
  46. library(maptools)
  47. library(spThin) # error here
  48. library(sdm)
  49. library(ecospat)
  50. library(ade4)
  51. library(dichromat)
  52. library(terra)
  53. # ENM model packages
  54. packs <- c('ade4', 'adehabitatMA', 'adehabitatHR', 'alphahull', 'dismo', 'dplyr', 'ecospat', 'ggplot2', 'jsonlite',
  55. 'kuenm', 'matrixStats', 'raster', 'rgdal', 'rgeos', 'rJava',
  56. 'sf', 'sp', 'splitstackshape', 'tidyr', 'utils', 'wesanderson', 'PerformanceAnalytics', 'SDMTools')
  57. # loading in the packages
  58. lapply(packs, library, character.only=T)
  59. # giving the package versions
  60. packs.df <- as.data.frame(matrix(NA, nrow=length(packs), ncol=2))
  61. colnames(packs.df) <- c('pkg.name', 'pkg.version')
  62. for(i in 1:length(packs)){
  63. packs.df[i,1] <- packs[i]
  64. packs.df[i,2] <- as.character(packageVersion(packs[i]))
  65. }
  66. packs.df
  67. library(raster)
  68. library(rasterize)
  69. ########################### FUNCTIONS #########
  70. ##### Prep Parameters ------------------------------------------------------------------------------------------------------
  71. # Prep Parameters for Maxent models in R with the dismo package
  72. # sourced from https://github.com/shandongfx/workshop_maxent_R/blob/master/code/Appendix2_prepPara.R
  73. # https://github.com/shandongfx/workshop_maxent_R/blob/master/code
  74. # should be used in concert with Appendix 3 from Feng et al. 2017 (PeerJ Preprints)
  75. # https://peerj.com/preprints/3346.pdf (manuscript still unpublished as of August 2020)
  76. # Appendix 3
  77. # https://github.com/shandongfx/workshop_maxent_R/blob/master/code/Appendix3_maxentParameters_v2.pdf
  78. # some arguments may change, or may/may not be used depending on if you're using raster data vs "samples-with-data" (SWD; column data)
  79. # A function that implements Maxent parameters using the general R manner
  80. # leave "doclamp" as default - later in the code (internal fxns run), "doclamp" is set to FALSE
  81. prepPara <- function(userfeatures=NULL, # 41 NULL=autofeature, could be any combination of # c("L", "Q", "H", "P", "T")
  82. # MUST be specified as a single string (e.g., "LQ", "LQP", "LQHPT", etc.)
  83. responsecurves=TRUE, # 1
  84. jackknife=TRUE, # 3
  85. outputformat="logistic", # 4
  86. outputfiletype="asc", # 5
  87. projectionlayers=NULL, # 7
  88. randomseed=FALSE, # 10
  89. removeduplicates=TRUE, # 16
  90. betamultiplier=NULL, # 20, 53-56
  91. biasfile=NULL, # 22
  92. testsamplesfile=NULL, # 23
  93. replicates=1, # 24-25
  94. replicatetype="crossvalidate", # 24-25
  95. writeplotdata=TRUE, # 37
  96. extrapolate=TRUE, # 39
  97. doclamp=TRUE, # 42
  98. beta_threshold=NULL, # 20, 53-56
  99. beta_categorical=NULL, # 20, 53-56
  100. beta_lqp=NULL, # 20, 53-56
  101. beta_hinge=NULL, # 20, 53-56
  102. applythresholdrule=NULL # 60
  103. ){
  104. #20, 29-33, & 41 features, default is autofeature
  105. if(is.null(userfeatures)){
  106. args_out <- c("autofeature")
  107. } else {
  108. args_out <- c("noautofeature")
  109. if(grepl("L",userfeatures)) args_out <- c(args_out,"linear") else args_out <- c(args_out,"nolinear")
  110. if(grepl("Q",userfeatures)) args_out <- c(args_out,"quadratic") else args_out <- c(args_out,"noquadratic")
  111. if(grepl("H",userfeatures)) args_out <- c(args_out,"hinge") else args_out <- c(args_out,"nohinge")
  112. if(grepl("P",userfeatures)) args_out <- c(args_out,"product") else args_out <- c(args_out,"noproduct")
  113. if(grepl("T",userfeatures)) args_out <- c(args_out,"threshold") else args_out <- c(args_out,"nothreshold")
  114. }
  115. # 1 - generate response curves for each variable
  116. if(responsecurves) args_out <- c(args_out,"responsecurves") else args_out <- c(args_out,"noresponsecurves")
  117. # 2
  118. #if(picture) args_out <- c(args_out,"pictures") else args_out <- c(args_out,"nopictures")
  119. # 3 - apply variable jackknife to see how the model changes if that variable is omitted, then if it's the ONLY variable used
  120. if(jackknife) args_out <- c(args_out,"jackknife") else args_out <- c(args_out,"nojackknife")
  121. # 4 - output format type. choose from c("logistic", "cumulative", "raw")
  122. args_out <- c(args_out,paste0("outputformat=",outputformat))
  123. # 5 - output file type. choose from c("asc", "mxe", "grd", "bil")
  124. args_out <- c(args_out,paste0("outputfiletype=",outputfiletype))
  125. # 7 - pathway to projection layers.
  126. # it seems that the projection layers should be the only files in that folder, just like with the MaxEnt .jar file
  127. if(!is.null(projectionlayers)) args_out <- c(args_out,paste0("projectionlayers=",projectionlayers))
  128. # 10 - will use different random number generators for selecting training vs testing data and background points (if applicable)
  129. if(randomseed) args_out <- c(args_out,"randomseed") else args_out <- c(args_out,"norandomseed")
  130. # 16 - remove duplicate coordinates that are in the same grid - ONLY for raster data, not SWD
  131. if(removeduplicates) args_out <- c(args_out,"removeduplicates") else args_out <- c(args_out,"noremoveduplicates")
  132. # 20 & 53-56 - various beta (regularization) multipliers to be applied. default = 1
  133. # 20 applies all parameters by this regularization multiplier.
  134. # 53-56 can apply uniquely to different feature types
  135. # check if negative
  136. betas <- c( betamultiplier,beta_threshold,beta_categorical,beta_lqp,beta_hinge)
  137. if(! is.null(betas) ){
  138. for(i in 1:length(betas)){
  139. if(betas[i] <0) stop("betamultiplier has to be positive")
  140. }
  141. }
  142. if ( !is.null(betamultiplier) ){
  143. args_out <- c(args_out,paste0("betamultiplier=",betamultiplier))
  144. } else {
  145. if(!is.null(beta_threshold)) args_out <- c(args_out,paste0("beta_threshold=",beta_threshold))
  146. if(!is.null(beta_categorical)) args_out <- c(args_out,paste0("beta_categorical=",beta_categorical))
  147. if(!is.null(beta_lqp)) args_out <- c(args_out,paste0("beta_lqp=",beta_lqp))
  148. if(!is.null(beta_hinge)) args_out <- c(args_out,paste0("beta_hinge=",beta_hinge))
  149. }
  150. # 22 - pathway to a bias file for selecting background points - ONLY for raster data, not SWD
  151. if(!is.null(biasfile)) args_out <- c(args_out,paste0("biasfile=",biasfile))
  152. # 23 - pathway to a test data file - can be in csv format
  153. if(!is.null(testsamplesfile)) args_out <- c(args_out,paste0("testsamplesfile=",testsamplesfile))
  154. # 24 - replicates = number of replicates to run (integer)
  155. # 25 - replicatetype = what type of replicates to run. choose from c('crossvalidate', 'bootstrap', 'subsample')
  156. replicates <- as.integer(replicates)
  157. if(replicates>1 ){
  158. args_out <- c(args_out,
  159. paste0("replicates=",replicates),
  160. paste0("replicatetype=",replicatetype) )
  161. }
  162. # 37 - write output files containing the data used to make response curves
  163. if(writeplotdata) args_out <- c(args_out,"writeplotdata") else args_out <- c(args_out,"nowriteplotdata")
  164. # 39 - allow extrapolation beyond the limits of the training data
  165. if(extrapolate) args_out <- c(args_out,"extrapolate") else args_out <- c(args_out,"noextrapolate")
  166. # 42 - apply clamping when projecting
  167. if(doclamp) args_out <- c(args_out,"doclamp") else args_out <- c(args_out,"nodoclamp")
  168. # 60 - threshold your model to binary 1/0
  169. # options are: c('Fixed cumulative value 1', 'Fixed cumulative value 5', 'Fixed cumulative value 10', 'Minimum training presence',
  170. # '10 percentile training presence', 'Equal training sensitivity and specificity', 'Maximum training sensitivity plus specificity').
  171. if(!is.null(applythresholdrule)) args_out <- c(args_out,paste0("applythresholdrule=",applythresholdrule))
  172. return(args_out)
  173. }
  174. # prepPara()
  175. # [1] "autofeature" "responsecurves" "jackknife" "outputformat=logistic" "outputfiletype=asc"
  176. # [6] "norandomseed" "removeduplicates" "writeplotdata" "extrapolate" "doclamp"
  177. ##### Create Null Object, Summary Object, Eval Object, and Nested File Structure -------------------------------------------
  178. ### functions that create the null data.frame, summary data.frame, and the eval data.frame
  179. ### ARGUMENTS ###
  180. ### arguments that exist to keep track of everything and do not change how the functions run
  181. ## taxon.name <- name of the entity that will get assigned to any null/summary/eval objects. Does not change how function runs.
  182. ## time.bin <- name of the time bin that will get assigned to any null/summary/eval objects. Does not change how function runs.
  183. ## extent <- name of the extent that will get assigned to any null/summary/eval objects. Does not change how function runs.
  184. ### arguments that set the model hyper-parameters and will change how the functions run
  185. ## cv.runs <- name(s) of the cross-validation types. folders will be generated with these names in create.folders.for.maxent.
  186. # recommended framework is to treat each cross-validation fold as a letter.
  187. # In the case of 5-fold cross validation, for running all the data (using the null.aic and optimize.maxent.likelihood . . .
  188. # . . . functions), you should specify 'abcde'. For running cross validation models with maxent.crossval.error, you . . .
  189. # . . . should specify c('abcd', 'abce', 'abde', 'acde', 'bcde').
  190. ## f.class <- name(s) of the feature classes used in analysis.
  191. ## beta.values <- regularization multipliers used in analysis
  192. # create.summary.df and create.eval.df will create every possible combination of cv.runs, f.class, and beta.values
  193. # function to create the null data.frame
  194. create.null.df <- function(taxon.name, time.bin, extent){
  195. null.object <- as.data.frame(matrix(NA, nrow=1, ncol=17))
  196. colnames(null.object) <- c( "Taxa", "Time.Bin", "Extent", "CrossVal", "cv.num", "Features", "Betas", "n", "k",
  197. "ln.L", "AIC", "AICc", "delta.i", "delta.i.c", "w.i", "w.i.c", "lambdas" )
  198. null.object$Taxa <- taxon.name
  199. null.object$Time.Bin <- time.bin
  200. null.object$Extent <- extent
  201. null.object$CrossVal <- 'abcde'
  202. null.object$cv.num <- 1
  203. null.object$lambdas <- 'Incercept'
  204. return(null.object)
  205. }
  206. # function to create the summary data.frame
  207. create.summary.df <- function(taxon.name,
  208. time.bin,
  209. extent,
  210. cv.runs = 'abcde',
  211. f.class = c('LQP', 'Q'),
  212. beta.values = c(0.025, 0.05, 0.1, 0.25, 0.5, 0.75, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5) ){
  213. summary.object <- expand.grid(CrossVal=cv.runs, Features = f.class, Betas = beta.values, stringsAsFactors = T)
  214. summary.object$cv.num <- as.numeric(summary.object$CrossVal)
  215. # ifelse functions defining what to do if taxon.name, time.bin, and extent are not specified
  216. if( !is.null(taxon.name) ){
  217. summary.object$Taxa <- taxon.name
  218. } else {
  219. summary.object$Taxa <- 'Taxon1'
  220. }
  221. if( !is.null(time.bin) ){
  222. summary.object$Time.Bin <- time.bin
  223. } else {
  224. summary.object$Time.Bin <- 'TimeBin1'
  225. }
  226. if( !is.null(extent) ){
  227. summary.object$Extent <- extent
  228. } else {
  229. summary.object$Extent <- 'Extent1'
  230. }
  231. # re-ordering columns
  232. summary.object <- summary.object[,c(5:7, 1, 4, 2:3)]
  233. # adding in all the other parameters
  234. summary.object$n <- NA # sample size
  235. summary.object$k <- NA # number of non-zero lambdas
  236. summary.object$ln.L <- NA # log-likelihood
  237. summary.object$AIC <- NA # AIC
  238. summary.object$AICc <- NA # AICc corrected for small sample size
  239. summary.object$delta.i <- NA # delta.i for AIC - wont calculate everything until all models have been run
  240. summary.object$delta.i.c <- NA # delta.i for AICc - wont calculate everything until all models have been run
  241. summary.object$w.i <- NA # Akaike Weights for AIC - wont calculate everything until all models have been run
  242. summary.object$w.i.c <- NA # Akaike Weights for AIC - wont calculate everything until all models have been run
  243. summary.object$lambdas <- NA # list of all the non-zero lambdas
  244. summary.object[,4] <- as.character(summary.object[,4])
  245. summary.object[,6] <- as.character(summary.object[,6])
  246. return(summary.object)
  247. }
  248. # function to create the eval data.frame
  249. create.eval.df <- function(taxon.name,
  250. time.bin,
  251. extent,
  252. cv.runs = c('abcd', 'abce', 'abde', 'acde', 'bcde'),
  253. f.class = 'LQP',
  254. beta.values = 1 ){
  255. summary.object <- expand.grid(CrossVal=cv.runs, Features = f.class, Betas = beta.values, stringsAsFactors = T)
  256. summary.object$cv.num <- 1:length(cv.runs)
  257. # ifelse functions defining what to do if taxon.name, time.bin, and extent are not specified
  258. if( !is.null(taxon.name) ){
  259. summary.object$Taxa <- taxon.name
  260. } else {
  261. summary.object$Taxa <- 'Taxon1'
  262. }
  263. if( !is.null(time.bin) ){
  264. summary.object$Time.Bin <- time.bin
  265. } else {
  266. summary.object$Time.Bin <- 'TimeBin1'
  267. }
  268. if( !is.null(extent) ){
  269. summary.object$Extent <- extent
  270. } else {
  271. summary.object$Extent <- 'Extent1'
  272. }
  273. # re-ordering columns
  274. summary.object <- summary.object[,c(5:7, 1, 4, 2:3)]
  275. # adding in all the other parameters
  276. summary.object$n <- NA # sample size
  277. summary.object$k <- NA # number of non-zero lambdas
  278. summary.object$ln.L <- NA # log-likelihood
  279. summary.object$AIC <- NA # AIC
  280. summary.object$AICc <- NA # AICc corrected for small sample size
  281. summary.object$delta.i <- NA # delta.i for AIC - wont calculate everything until all models have been run
  282. summary.object$delta.i.c <- NA # delta.i for AICc - wont calculate everything until all models have been run
  283. summary.object$w.i <- NA # Akaike Weights for AIC - wont calculate everything until all models have been run
  284. summary.object$w.i.c <- NA # Akaike Weights for AIC - wont calculate everything until all models have been run
  285. summary.object$lambdas <- NA # list of all the non-zero lambdas
  286. summary.object[,4] <- as.character(summary.object[,4])
  287. summary.object[,6] <- as.character(summary.object[,6])
  288. # renaming the columns
  289. colnames(summary.object) <- c('Taxa', 'Time.Bin', 'Extent', 'CrossVal', 'cv.num', 'Features', 'Betas', 'n', 'thresh', 'test.sens',
  290. 'pROC_0.1', 'pval_0.1', 'pROC_1', 'pval_1', 'pROC_5', 'pval_5', 'lambdas')
  291. return(summary.object)
  292. }
  293. # function to create the nested fie structure that it will use to store the output (including html files) of maxent models
  294. # summary.eval.df <- the summary.df data.frame or the eval.df data.frame.
  295. # the function will use information from the cv.runs, f.class, and beta.values columns to create this nested file structure
  296. # wd <- working directory that the nested file structure is going to be generated in. if running multiple species, it is recommended . . .
  297. # . . . that you make a folder for each species, then run this function in each species folder
  298. create.folders.for.maxent <- function(summary.eval.df, wd = getwd() ){
  299. # setting the working directory
  300. setwd( getwd() )
  301. # for loop that goes through the summary/evaluation data.frame and creates the nested file structure
  302. for( i in 1:nrow(summary.eval.df) ){
  303. if( !dir.exists( paste(getwd(), summary.eval.df$CrossVal[i], sep='/' ) ) ){ # if the cross-validation folder exists
  304. writeLines( c('Creating folder:', paste(getwd(), summary.eval.df$CrossVal[i], sep='/'), sep='') )
  305. dir.create( paste(getwd(), summary.eval.df$CrossVal[i], sep='/') )
  306. setwd( paste(getwd(), summary.eval.df$CrossVal[i], sep='/') )
  307. } else {
  308. setwd( paste(getwd(), summary.eval.df$CrossVal[i], sep='/') )
  309. }
  310. if( !dir.exists( paste(getwd(), summary.eval.df$Features[i], sep='/' ) ) ){ # if the feature class folder exists
  311. writeLines( c('Creating folder:', paste(getwd(), summary.eval.df$Features[i], sep='/'), sep='') )
  312. dir.create( paste(getwd(), summary.eval.df$Features[i], sep='/') )
  313. setwd( paste(getwd(), summary.eval.df$Features[i], sep='/') )
  314. } else {
  315. setwd( paste(getwd(), summary.eval.df$Features[i], sep='/') )
  316. }
  317. if( !dir.exists( paste(getwd(), summary.eval.df$Features[i], sep='/' ) ) ){ # if the regularization folder exists
  318. writeLines( c('Creating folder:', paste(getwd(), paste('beta', summary.eval.df$Betas[i], sep='_'), sep='/'), sep='') )
  319. dir.create( paste(getwd(), paste('beta', summary.eval.df$Betas[i], sep='_'), sep='/') )
  320. setwd( paste(getwd(), paste('beta', summary.eval.df$Betas[i], sep='_'), sep='/') )
  321. } else {
  322. setwd( paste(getwd(), paste('beta', summary.eval.df$Betas[i], sep='_'), sep='/') )
  323. }
  324. setwd('../../../') # go three directories back
  325. } # finishing main for loop
  326. }
  327. # setwd("~/Dropbox/SVP_Models/ModelOutput/Tyrano")
  328. #
  329. #
  330. # examp <- create.summary.df('Tyrano', 'K', 'Laurimidia')
  331. # examp2 <- create.eval.df('Tyrano', 'K', 'Laurimidia')
  332. #
  333. #
  334. # create.folders.for.maxent(examp)
  335. # create.folders.for.maxent(examp2)
  336. ##### Optimize MaxEnt Likelihood -------------------------------------------------------------------------------------------
  337. # function that runs all the maxent models.
  338. # function will return a filled out summary model
  339. optimize.maxent.likelihood <- function(summary.df, # summary object that will keep all the model output
  340. # the nested file structure created from create.folders.for.maxent MUST exist
  341. occs, # species occurrence object
  342. background, # sampled Background object (COLUMNS MUST BE IDENTICAL TO occs)
  343. predic, # column numbers of the predictor variables
  344. first.occ.col, # number of the first cross-validation column in occs/background
  345. home=getwd(), # directory where all the models will be ran.
  346. all.models = TRUE # do you want to keep all versions of all the models?
  347. # helpful for quickly checking some models, but may consume loads (e.g., >1GB) . . .
  348. # . . . of hard disk space. Recommended to set to FALSE for exploratory analyses.
  349. # if FALSE, function will create a folder called "RunOver" and will . . .
  350. # . . . continuously write-over it for all models, and the only model you see . . .
  351. # . . . at the end will be the last model that was ran
  352. ){
  353. # Calculating the total number of models
  354. nmodels <- nrow(summary.df)
  355. # prompting the user if they want to store models in the RAM
  356. print(paste0('The time is ', Sys.time(), '. You are running ', nmodels, ' total MaxEnt models.'))
  357. # setting up the progress bar
  358. prog <- txtProgressBar(min=0, max=nrow(summary.df), style=3, char='+')
  359. for(i in 1:nrow(summary.df)){
  360. # setting the working directory for each folder
  361. if(all.models == TRUE){
  362. setwd( paste(home, summary.df[i,4], summary.df[i,6], paste('beta', summary.df[i,7], sep='_'), sep='/') )
  363. } else {
  364. # create the RunOver folder
  365. if( !dir.exists( paste(home, 'RunOver', sep='/') ) ){
  366. dir.create( paste(home, 'RunOver', sep='/') )
  367. setwd( paste(home, 'RunOver', sep='/') )
  368. } else {
  369. setwd( paste(home, 'RunOver', sep='/') )
  370. }
  371. }
  372. ###########################################################################
  373. ### MaxEnt things happen here
  374. ### preparing the data for the maxent model
  375. # filtering the occ object by it's respective cross-validation identity
  376. cv.number <- summary.df$cv.num[i]
  377. # assigning the column number to be sent through maxent
  378. col.number <- first.occ.col + cv.number - 1
  379. # filtering the species dataset by col.number and assigning to summary.df
  380. sp <- occs %>% dplyr::filter(occs[,col.number] == 1)
  381. n <- nrow(sp)
  382. summary.df[i,8] <- n
  383. # bending the occ and background data together
  384. mx.data <- rbind(sp, background)
  385. ### running the actual maxent model
  386. mx.model <- dismo::maxent(p = mx.data[,col.number],
  387. x = mx.data[,predic],
  388. path = paste0(getwd()),
  389. args = prepPara(userfeatures = summary.df[i,6], betamultiplier = summary.df[i,7], doclamp = FALSE)
  390. )
  391. ### calculating k and the names of the lambdas
  392. lambda.file <- as.data.frame(mx.model@lambdas) %>% `colnames<-`('lambdas')
  393. # lambdas data frame
  394. lambdas.df <- splitstackshape::cSplit(lambda.file, sep=',', splitCols='lambdas')
  395. colnames(lambdas.df) <- c('feature', 'lambda', 'min', 'max')
  396. # finding the non-zero lambdas
  397. non.zero.lambdas <- lambdas.df %>% dplyr::filter(!is.na(max)) %>% dplyr::filter(lambda != 0)
  398. class(non.zero.lambdas) <- 'data.frame'
  399. # assigning the number of parameters
  400. k <- nrow(non.zero.lambdas)
  401. # if beta is too high, the model gets over-regularized to the point that all the lambda coefficients get set to 0
  402. # this effectively becomes an intercept only model, which is effectively the global mean
  403. # in this sense, k should get set to 0
  404. if(k == 0){
  405. k <- 1
  406. }
  407. summary.df[i,9] <- k
  408. # giving noting the variables/features/hyperparameters with non-zero lambdas
  409. summary.df[i,17] <- toString(non.zero.lambdas[,1])
  410. ### calculating the log-likelihood, then AIC and AICc
  411. # if statement calculating if there is an appropriate AIC value
  412. # e.g., can't fit 4 observations (occurrence points) with 5 variables
  413. if(n - k < 2){
  414. summary.df[i,10] <- NA
  415. summary.df[i,11] <- NA
  416. summary.df[i,12] <- NA
  417. } else { # if it is possible to calculate AIC and AICc
  418. # logistic model output
  419. mx.back <- dismo::predict(mx.model, background[,predic])
  420. # sum of all background point values - mx.back / back.sum should = 1
  421. back.sum <- sum(mx.back)
  422. # logistic values of the (k-1)/k occurrences
  423. mx.occs <- dismo::predict(mx.model, sp[,predic])
  424. # scaling to make compatible for calculating AIC
  425. occs.raw <- mx.occs / back.sum
  426. # log(likelihood)
  427. log.like <- sum(log(occs.raw))
  428. summary.df[i,10]<- log.like
  429. ### calculating AIC and AICc
  430. # AIC
  431. AIC <- 2*k - 2*log.like
  432. summary.df[i,11] <- AIC
  433. # AICc
  434. summary.df[i,12] <- AIC + 2*((k^2 + k) / (n - k - 1))
  435. }
  436. # updating the prograss bar for each run to get an idea of how long things will take
  437. setTxtProgressBar(prog, i)
  438. ###########################################################################
  439. # returning to the home directory
  440. setwd(home)
  441. } # closes the for loop
  442. return(summary.df)
  443. }
  444. ##### Null AICc ------------------------------------------------------------------------------------------------------------
  445. # function that calculates AIC and AICc values for a null intercept-only model
  446. # the arguments are the same as the optimize.maxent.likelihood model, except that null.df should be a data.frame created from the . . .
  447. # . . . create.null.df object
  448. # function will return
  449. null.aic <- function(null.df, occs, background, first.occ.col){
  450. # number of parameters
  451. null.df$k <- 1
  452. # assigning the column number to be sent through maxent
  453. col.number <- first.occ.col
  454. # filtering the species dataset by col.number and assigning to null.df
  455. sp <- occs %>% dplyr::filter(occs[,col.number] == 1)
  456. n <- nrow(sp)
  457. null.df[1,8] <- n
  458. # giving noting the variables/features/hyperparameters with non-zero lambdas
  459. null.df[1,17] <- 'Intercept'
  460. out.scale <- rep(1, times=n ) / nrow(background)
  461. log.like <- sum(log(out.scale))
  462. null.df[1,10] <- log.like
  463. ### calculating AIC and AICc
  464. # AIC
  465. AIC <- 2 - 2*log.like
  466. null.df[1,11] <- AIC
  467. # AICc for one term null model
  468. null.df[1,12] <- AIC + 4/(n - 2)
  469. return(null.df)
  470. }
  471. ##### MaxEnt Cross-Validation Error -----------------------------------------------------------------------------------------------
  472. # function that runs five-fold cross-validation once you've found the optimum hyper-parameters for your maxent model(s)
  473. # functions returns a list containing 3 objects: 1.) a filled out eval object; 2.) an object containing all the maxent models; and . . .
  474. # . . . 3.) a data.frame with dimensions [ 1:nrow(background), 1:nrow(eval.df) ] containing the projections of all the models in
  475. maxent.crossval.error <- function(eval.df, # object generated from create.eval.df that will keep all the model output
  476. occs, # species occurrence object
  477. background, # sampled Background object (COLUMNS MUST BE IDENTICAL TO occs)
  478. predic, # column numbers of the predictor variables
  479. first.occ.col, # number of the first training in occs/background (assumes k = 5)
  480. # NOTE: this is not the presence column! it's the column to the right of it
  481. first.test.col, # number of the first testing column in occs/background (assumes k = 5)
  482. home=getwd(), # directory where all the models will be ran
  483. all.models = TRUE, # do you want to keep all versions of all the models?
  484. # helpful for quickly checking some models, but may consume loads (e.g., >1GB) . . .
  485. # . . . of hard disk space. Recommended to set to FALSE for exploratory analyses.
  486. # if FALSE, function will create a folder called "RunOver" and will . . .
  487. # . . . continuously write-over it for all models, and the only model you see . . .
  488. # . . . at the end will be the last model that was ran
  489. omission.rate=0, # user specified omission rate to be calculated for the threshold
  490. # express as a proportion from 0-1
  491. all.background, # background data from the extents the species exists in
  492. # if using all the potential background points, all.background should == background
  493. pROC.reps = 500 # number of iterations each partialROC test will go through
  494. ){
  495. # Calculating the total number of models
  496. nmodels <- nrow(eval.df)
  497. # stop if an incompatible omission rate is specified
  498. if(omission.rate > 1 || omission.rate < 0){
  499. stop('Specify an omission rate between 0-1.')
  500. }
  501. # prompting the user if they want to store models in the RAM
  502. print(paste0('The time is ', Sys.time(), '. You are running ', nmodels, ' total MaxEnt models.'))
  503. # setting up the progress bar
  504. prog <- txtProgressBar(min=0, max=nrow(eval.df), style=3, char='+')
  505. # setting up various list objects to send output to
  506. # list for the maxent models
  507. maxent.list <- list()
  508. # list for the testing background data
  509. test.back.list <- list()
  510. # list for all the occs
  511. all.occs.list <- list()
  512. for(i in 1:nrow(eval.df)){
  513. # setting the working directory for each folder
  514. if(all.models == TRUE){
  515. setwd( paste(home, eval.df[i,4], eval.df[i,6], paste('beta', eval.df[i,7], sep='_'), sep='/') )
  516. } else {
  517. # create the RunOver folder
  518. if( !dir.exists( paste(home, 'RunOver', sep='/') ) ){
  519. dir.create( paste(home, 'RunOver', sep='/') )
  520. setwd( paste(home, 'RunOver', sep='/') )
  521. } else {
  522. setwd( paste(home, 'RunOver', sep='/') )
  523. }
  524. }
  525. ###########################################################################
  526. ### MaxEnt things happen here
  527. ### preparing the data for the maxent model
  528. # filtering the occ object by it's respective cross-validation identity
  529. cv.number <- eval.df$cv.num[i]
  530. # assigning the column number to be sent through maxent
  531. col.number <- first.occ.col + cv.number - 1
  532. # filtering the species dataset by col.number and assigning to eval.df
  533. sp <- occs %>% dplyr::filter(occs[,col.number] == 1)
  534. n <- nrow(sp)
  535. eval.df[i,8] <- n
  536. # generating the testing data
  537. test.col.number <- first.test.col + cv.number - 1
  538. sp.test <- occs %>% dplyr::filter(occs[,test.col.number] == 1)
  539. # bending the occ and background data together
  540. mx.data <- rbind(sp, background)
  541. ### running the actual maxent model
  542. mx.model <- dismo::maxent(p = mx.data[,col.number],
  543. x = mx.data[,predic],
  544. path = paste0(getwd()),
  545. args = prepPara(userfeatures = eval.df[i,6], betamultiplier = eval.df[i,7], doclamp = FALSE)
  546. )
  547. ### calculating k and the names of the lambdas
  548. lambda.file <- as.data.frame(mx.model@lambdas) %>% `colnames<-`('lambdas')
  549. # lambdas data frame
  550. lambdas.df <- splitstackshape::cSplit(lambda.file, sep=',', splitCols='lambdas')
  551. colnames(lambdas.df) <- c('feature', 'lambda', 'min', 'max')
  552. # finding the non-zero lambdas
  553. non.zero.lambdas <- lambdas.df %>% dplyr::filter(!is.na(max)) %>% dplyr::filter(lambda != 0)
  554. class(non.zero.lambdas) <- 'data.frame'
  555. # giving noting the variables/features/hyperparameters with non-zero lambdas
  556. eval.df[i,17] <- toString( non.zero.lambdas[,1] )
  557. ## evaluating the models
  558. # predicting the training data
  559. mx.train.occ <- dismo::predict(mx.model, sp[,predic])
  560. # predicting the training background data
  561. mx.train.back <- dismo::predict(mx.model, background[,predic])
  562. # predicting the testing data
  563. mx.test.occ <- dismo::predict(mx.model, sp.test[,predic])
  564. # projecting to all extents
  565. mx.test.back <- dismo::predict(mx.model, all.background[,predic])
  566. # projecting to all occ points
  567. mx.all.occs <- dismo::predict(mx.model, occs[,predic])
  568. # calculate the threshold
  569. if(omission.rate == 0){ # if using the LTP threshold, dismo calculates slightly too high of a threshold
  570. thresh <- min(mx.train.occ)
  571. } else {
  572. # make a model evaluation object
  573. mx.eval <- dismo::evaluate(p=mx.train.occ, a=mx.train.back)
  574. thresh <- dismo::threshold(mx.eval, stat='sensitivity', sensitivity= (1 - omission.rate) )
  575. }
  576. # assigning the threshold value to the output file
  577. eval.df[i,9] <- thresh
  578. # calculating the test sensitivity
  579. sens <- length(which(mx.test.occ >= thresh)) / length(mx.test.occ)
  580. eval.df[i,10] <- sens
  581. # making a raster of the testing background data
  582. # for some reason, kuenm calculates wonky AUC_ratio values (i.e., > 2, which is impossible) unless you specify a raster
  583. r <- raster(nrows=1, ncols=length(mx.test.back) )
  584. r[r] <- mx.test.back
  585. ## calculating AUC_ratios from a partialROC test
  586. # error = 0.1%
  587. pROC_0.1 <- kuenm::kuenm_proc(occ.test = mx.test.occ, # numeric vector of the predicted suitability values on the testing data
  588. model = r, # raster model of the predicted suitability values for the background
  589. threshold = 0.1, # potential error threshold (expressed as a percent)
  590. rand.percent = 50, # percentage of data to be used in each bootstrap rep
  591. iterations = pROC.reps # number of repititions
  592. )
  593. # assigning the average AUC_ratio from pROC.reps iterations to eval.df
  594. eval.df[i,11] <- as.numeric(pROC_0.1$pROC_summary[1])
  595. # assigning the partialROC p-value to eval.df
  596. eval.df[i,12] <- as.numeric(pROC_0.1$pROC_summary[2])
  597. # error = 1%
  598. pROC_1 <- kuenm::kuenm_proc(occ.test = mx.test.occ, # numeric vector of the predicted suitability values on the testing data
  599. model = r, # raster model of the predicted suitability values for the background
  600. threshold = 1, # potential error threshold (expressed as a percent)
  601. rand.percent = 50, # percentage of data to be used in each bootstrap rep
  602. iterations = pROC.reps # number of repititions
  603. )
  604. # assigning the average AUC_ratio from pROC.reps iterations to eval.df
  605. eval.df[i,13] <- as.numeric(pROC_1$pROC_summary[1])
  606. # assigning the partialROC p-value to eval.df
  607. eval.df[i,14] <- as.numeric(pROC_1$pROC_summary[2])
  608. # error = 5%
  609. pROC_5 <- kuenm::kuenm_proc(occ.test = mx.test.occ, # numeric vector of the predicted suitability values on the testing data
  610. model = r, # raster model of the predicted suitability values for the background
  611. threshold = 5, # potential error threshold (expressed as a percent)
  612. rand.percent = 50, # percentage of data to be used in each bootstrap rep
  613. iterations = pROC.reps # number of repititions
  614. )
  615. # assigning the average AUC_ratio from pROC.reps iterations to eval.df
  616. eval.df[i,15] <- as.numeric(pROC_5$pROC_summary[1])
  617. # assigning the partialROC p-value to eval.df
  618. eval.df[i,16] <- as.numeric(pROC_5$pROC_summary[2])
  619. mx.test.back.df <- as.data.frame( as.matrix(mx.test.back, ncol=1) )
  620. # assigning the objects to the various lists
  621. maxent.list[[i]] <- mx.model
  622. test.back.list[[i]] <- mx.test.back
  623. all.occs.list[[i]] <- mx.all.occs
  624. # updating the prograss bar for each run to get an idea of how long things will take
  625. setTxtProgressBar(prog, i)
  626. ###########################################################################
  627. # returning to the home directory
  628. setwd(home)
  629. } # closes the for loop
  630. # bind the testing background data into a single data
  631. back.projections <- as.data.frame( do.call('cbind', test.back.list ) )
  632. colnames(back.projections) <- eval.df$CrossVal
  633. # bind all occs together
  634. occ.projections <- as.data.frame(do.call('cbind', all.occs.list))
  635. colnames(occ.projections) <- eval.df$CrossVal
  636. # make a list of the output
  637. out.list <- list()
  638. out.list$maxent.models <- maxent.list
  639. out.list$back.projection <- back.projections
  640. out.list$occ.projection <- occ.projections
  641. out.list$summary <- eval.df
  642. return(out.list)
  643. }
  644. ##### MaxEnt Evaluation ----------------------------------------------------------------------------------------------------
  645. # function that takes the eval object generated from maxent.crossval.error and calculates the weighted mean and standard deviation
  646. # the weighted mean is calculating my testing sensitivity (1 - omission rate) multiplied by the partial ROC/AUC value.
  647. # this ensures that if a model does not discriminate between presences/non-presences well, it will receive comparatively lower weight
  648. # later package versions will include Boyce index as an additional calibration technique and will offer the user the ability to . . .
  649. # . . . choose which metrics to use for assessing model reliability
  650. # the weighted mean and standard deviation can be plotted to infer model variability/uncertainty
  651. ### ARGUMENTS ###
  652. ## eval <- eval object generated from maxent.crossval.error that will project the model to every grid cell used in the training region
  653. ## pROC.error <- the user-specified omission rate.
  654. # (choose from 0.1, 1, 5 - however they almost always end up super correlated with each other)
  655. maxent.eval <- function(eval, pROC.error=1){
  656. # extracting model sensitivity
  657. sens <- eval$summary$test.sens
  658. # which pROC error amount to use?
  659. if(pROC.error == 0.1){
  660. AUC_ratio <- eval$summary$pROC_0.1
  661. } else if(pROC.error == 1){
  662. AUC_ratio <- eval$summary$pROC_1
  663. } else if(pROC.error == 5){
  664. AUC_ratio <- eval$summary$pROC_5
  665. } else {
  666. stop('Select an appropriate partialROC error amount.')
  667. }
  668. # weights = sensitivity*AUC_ratio
  669. weights <- sens * AUC_ratio
  670. weights[is.nan(weights)] <- 0
  671. # making a matrix of the background points
  672. models.mat <- as.matrix(eval$back.projection)
  673. # weighted means and standard deviations
  674. w.mean <- matrixStats::rowWeightedMeans(x=models.mat, w=weights)
  675. w.sd <- matrixStats::rowWeightedSds(x=models.mat, w=weights)
  676. # merging the weighted means/sd's of all background points
  677. back.df <- data.frame(w.mean, w.sd)
  678. # making a matrix of the background points
  679. occs.mat <- as.matrix(eval$occ.projection)
  680. # weighted means and standard deviations
  681. w.mean <- matrixStats::rowWeightedMeans(x=occs.mat, w=weights)
  682. w.sd <- matrixStats::rowWeightedSds(x=occs.mat, w=weights)
  683. # merging the weighted means/sd's of all occ points
  684. occ.df <- data.frame(w.mean, w.sd)
  685. # making the output list
  686. out.list <- list()
  687. out.list$back <- back.df
  688. out.list$occ <- occ.df
  689. out.list$weights <- weights
  690. return(out.list)
  691. }
  692. ##### Calculating the MaxEnt Threshold -------------------------------------------------------------------------------------
  693. # function that calculates the threshold value for all the training data
  694. ### ARGUMENTS ###
  695. ## eval <- eval object generated from maxent.crossval.error that will project the model to every grid cell used in the training region
  696. ## occs <- the occurrence data.frame
  697. ## predic <- column numbers of the predictor variables
  698. ## pROC.error <- the user-specified omission rate.
  699. # (choose from 0.1, 1, 5 - however they almost always end up super correlated with each other)
  700. # function will return the lowest training preference threshold.
  701. # future package versions will give the opportunity to select different thresholds
  702. maxent.thresh <- function(eval, occs, predic, pROC.error=1){
  703. n.rows <- nrow(occs)
  704. n.cols <- nrow(eval$summary)
  705. # making a data.frame of the occurrences
  706. occ.values <- as.data.frame( matrix(NA, nrow=n.rows, ncol=n.cols ) )
  707. colnames(occ.values) <- eval$summary$CrossVal
  708. # for loop predicting all the cross validation maxent models
  709. for(i in 1:nrow(eval$summary) ){
  710. mx.occs <- dismo::predict(object=eval$maxent.models[[i]], x=occs[,predic])
  711. occ.values[,i] <- mx.occs
  712. }
  713. #
  714. # extracting model sensitivity
  715. sens <- eval$summary$test.sens
  716. # which pROC error amount to use?
  717. if(pROC.error == 0.1){
  718. AUC_ratio <- eval$summary$pROC_0.1
  719. } else if(pROC.error == 1){
  720. AUC_ratio <- eval$summary$pROC_1
  721. } else if(pROC.error == 5){
  722. AUC_ratio <- eval$summary$pROC_5
  723. } else {
  724. stop('Select an appropriate partialROC error amount.')
  725. }
  726. # weights = sensitivity*AUC_ratio
  727. weights <- sens * AUC_ratio
  728. weights[is.nan(weights)]<- 0
  729. # making a matrix of the background points
  730. models.mat <- as.matrix(occ.values)
  731. # weighted means
  732. w.mean <- matrixStats::rowWeightedMeans(x=models.mat, w=weights)
  733. # setting the threshold as the lowest training presence
  734. ltp <- min(w.mean)
  735. return(ltp)
  736. }
  737. ##### Projecting the Best Models to All the Extents ------------------------------------------------------------------------
  738. # function to project models to any and all extents you want to
  739. # effectively making new master occurrence and master background files that can easily be saved and re-loaded again
  740. maxent.everything <- function(eval, means, everything, thresh, pROC.error=1, predic, name='pc'){
  741. # making a data.frame of the occurrences
  742. every.value <- as.data.frame( matrix(NA, nrow=nrow(everything), ncol=nrow(eval$summary)) )
  743. colnames(every.value) <- eval$summary$CrossVal
  744. # for loop predicting all the cross validation maxent models
  745. for(i in 1:nrow(eval$summary) ){
  746. mx.everything <- dismo::predict(object=eval$maxent.models[[i]], x=everything[,predic])
  747. every.value[,i] <- mx.everything
  748. }
  749. # extracting model sensitivity
  750. sens <- eval$summary$test.sens
  751. # which pROC error amount to use?
  752. if(pROC.error == 0.1){
  753. AUC_ratio <- eval$summary$pROC_0.1
  754. } else if(pROC.error == 1){
  755. AUC_ratio <- eval$summary$pROC_1
  756. } else if(pROC.error == 5){
  757. AUC_ratio <- eval$summary$pROC_5
  758. } else {
  759. stop('Select an appropriate partialROC error amount.')
  760. }
  761. # weights = sensitivity*AUC_ratio
  762. weights <- sens * AUC_ratio
  763. weights[is.nan(weights)] <- 0
  764. # making a matrix of the background points
  765. models.mat <- as.matrix(every.value)
  766. # weighted means
  767. w.mean <- matrixStats::rowWeightedMeans(x=models.mat, w=weights)
  768. # making the output data frame
  769. out.df <- as.data.frame( matrix(NA, nrow=length(w.mean), ncol=2) )
  770. colnames(out.df) <- c(paste0(eval$summary[1,1], '_contin'), paste0(eval$summary[1,1], '_thresh') )
  771. # assigning the weighted means to the output data.frame
  772. out.df[,1] <- w.mean
  773. # replicating the weighted means so they can be thresolded
  774. out.df[,2] <- w.mean
  775. # calculating the threshold
  776. thresh <- min(means$occ$w.mean)
  777. # thresolding the values
  778. out.df[,2][out.df[,2] >= thresh] <- 1
  779. out.df[,2][out.df[,2] < thresh] <- 0
  780. return(out.df)
  781. }
  782. ##### Informed Analysis -----------------------------------------------------------------------------------------------
  783. # function that calculates Multivariate Environmental Suitability Surface (MESS), but allows for some extrapolation . . .
  784. # . . . based on how response curves look.
  785. informed.mess <- function(ref.extent, # reference data.frame - must contain same column names as 'data'
  786. mess.extent, # data.frame containing the extent to be projected to - ideally this should be all extents
  787. coord.cols=2:3, # column numbers of the coordinates of the data/ref.data (e.g., long/lat)
  788. predic=6:11, # column numbers of ONLY the final predictor variables
  789. tolerance=NULL, # tolerance vector to extrapolate beyond the limits of the data. see example below
  790. # if tolerance is not specified (default), function will calculate basic MESS
  791. keep.layers=FALSE # decision to retain the MESS values for all variables instead of just the final MESS data
  792. # changing to TRUE can help easily identify which variables are causing the MESS value . . .
  793. # . . . to be so low (i.e., it may be only 1 variable that is responsible)
  794. # can easily re-check this later
  795. ){
  796. # isolating the coordinates and predictor variables
  797. new.vars <- mess.extent[, predic]
  798. ref.vars <- ref.extent[, predic]
  799. #
  800. if( !is.null(tolerance) ){
  801. if(length(predic) != length(tolerance)/2 ){
  802. stop('Ensure that tolerance is 2x as long as predic')
  803. }
  804. # changing tolerance to a data.frame
  805. tolerance <- as.data.frame( matrix(tolerance, ncol=2, byrow=TRUE) )
  806. nvars <- length(predic)
  807. # pre-changing values outside the range of the input data
  808. # extra rows
  809. extra.rows <- matrix(NA, nrow=2, ncol=nvars)
  810. colnames(extra.rows) <- colnames(ref.vars)
  811. ref.vars <- rbind(ref.vars, extra.rows )
  812. for(i in 1:nvars){
  813. # if we can extrapolate beyond the lower end of variable i, allow mess to not
  814. if(tolerance[i,1] == 1){
  815. min.var <- min(ref.vars[,i], na.rm=TRUE) - 0.0001
  816. new.vars[ new.vars[,i] < min.var, i ] <- min.var
  817. ref.vars[nrow(ref.vars)-1, i] <- min.var
  818. } else {
  819. ref.vars[nrow(ref.vars)-1, i] <- min(ref.vars[,i], na.rm=TRUE)
  820. }
  821. if(tolerance[i,2] == 1){
  822. max.var <- max(ref.vars[,i], na.rm=TRUE) + 0.0001
  823. new.vars[ new.vars[,i] > max.var, i ] <- max.var
  824. ref.vars[nrow(ref.vars), i] <- max.var
  825. } else {
  826. ref.vars[nrow(ref.vars), i] <- max(ref.vars[,i], na.rm=TRUE)
  827. }
  828. } # end for(i in 1:nvars) loop
  829. }
  830. # running the mess analysis
  831. mess.vars <- as.data.frame( sapply(1:ncol(new.vars), function(i) .messi3(new.vars[, i], ref.vars[, i])) )
  832. # re-asigning of the extrapolating points to have a mess value of 0.
  833. nref <- nrow(ref.vars)
  834. fix.vars <- as.data.frame( sapply(1:ncol(new.vars), function(i) .messi3(ref.vars[ (nref-1):nref , i], ref.vars[, i])) )
  835. for(i in 1:nvars){
  836. mess.vars[mess.vars[,i] == fix.vars[1,i],i] <- 0
  837. mess.vars[mess.vars[,i] == fix.vars[2,i],i] <- 0
  838. }
  839. # making a simple thresholded version of the mess analysis for easy plotting
  840. final.mess <- as.data.frame( apply(mess.vars, 1, min) )
  841. colnames(final.mess) <- 'mess.raw'
  842. mess.thresh <- final.mess$mess.raw
  843. mess.thresh[mess.thresh > 0] <- 1
  844. mess.thresh[mess.thresh < 0] <- -1
  845. final.mess <- cbind(final.mess, mess.thresh)
  846. # deciding whether to keep individual mess layers
  847. if(keep.layers==TRUE){
  848. colnames(ref.vars) <- paste0('mess_', colnames(ref.vars))
  849. final.mess <- cbind(final.mess, ref.vars)
  850. return(final.mess)
  851. } else {
  852. return(final.mess)
  853. }
  854. }
  855. # internal function originally from dismo that runs the actual mess analysis in data.frame format
  856. .messi3 <- function(p,v) { # p=new.vars v=ref.vars
  857. # seems 2-3 times faster than messi2
  858. v <- stats::na.omit(v)
  859. f <- 100*findInterval(p, sort(v)) / length(v)
  860. minv <- min(v)
  861. maxv <- max(v)
  862. res <- 2*f
  863. f[is.na(f)] <- -99
  864. i <- f>50 & f<100
  865. res[i] <- 200-res[i]
  866. i <- f==0
  867. res[i] <- 100*(p[i]-minv)/(maxv-minv)
  868. i <- f==100
  869. res[i] <- 100*(maxv-p[i])/(maxv-minv)
  870. res
  871. }
  872. ##### uncert.suit.plot -----------------------------------------------------------------------------------------------------
  873. suit.uncert.plot <- function(means){
  874. back <- means$back
  875. occs <- means$occ
  876. ltp <- min(occs$w.mean)
  877. output <- ggplot(data=back, aes(x=w.mean, y=w.sd)) + geom_point(colour='black', size=0.75) +
  878. geom_point(data=occs, aes(x=w.mean, y=w.sd), size=2, colour='red', shape=18 ) +
  879. ylim(0, 0.55) + xlim(0,1) + theme_classic() + coord_fixed(1/0.55) +
  880. annotate(geom='text', x=0.05, y=0.45, label=round(ltp, 4), hjust=0 )
  881. return(output)
  882. }
  883. # function that adds k-folds to the dataset
  884. ### Arguments ###
  885. # x <- vector or data.frame of your occurrences
  886. #
  887. # k <- number of folds you want to make
  888. #
  889. # seed <- value for set.seed in case you want to reproduce your exact k-fold samples in the future
  890. # returns a vector that has the same length as nrow(x) that contains the k-fold bin that the occurrences got assigned to
  891. make.kfolds <- function(x, k=5, seed=NULL){
  892. if(class(x) != "data.frame"){
  893. class(x) <- "data.frame"
  894. }
  895. n <- nrow(x)
  896. rep.times <- n %/% k # number of full reps for the rep function
  897. k.bins <- rep.times*k # number of occs minus any remainder when dividing by k
  898. remainder <- n - k.bins # find the remainder
  899. output <- rep(1:k, rep.times) # make k bins of equal size
  900. if(!is.null(seed)){
  901. set.seed(seed)
  902. }
  903. if(remainder != 0){ # if there is a remainder, . . .
  904. extra <- sample(x=1:k, size=remainder) # randomly sample it. . .
  905. output <- c(output, extra) # . . . and add it to the output
  906. }
  907. output <- sample(output, size=n) # randomize the order of the output
  908. return(output)
  909. }
  910. # function that makes a background file for each extent (time.bin and/or region) in the analysis
  911. # merging the background files for every extent will create the master background file
  912. ### ARGUMENTS ###
  913. # r.stack <- a raster stack containing all the predictor variables for analysis for a given extent
  914. # if using multiple extents, ensure that all the predictor variables have the exact same name and are in the same order
  915. # if testing multiple types of variables (i.e., GCM-based vs sedimentology-based), it is ideal to seperate them into . . .
  916. # . . . those two categories before reading them into R
  917. #
  918. # x.col <- the column name of the x-coordinate to be put in the background/occurrence objects
  919. # this MUST be consistent for all background/occurrence objects
  920. #
  921. # y.col <- the column name of the y-coordinate to be put in the background/occurrence objects
  922. # this MUST be consistent for all background/occurrence objects
  923. #
  924. # time.bin <- the name of the time.bin to be put in the background/occurrence objects
  925. # if only using a single time.bin, keep this consistent for all background/occurrence objects
  926. #
  927. # region <- the name of the region to be put in the background/occurrence objects
  928. # if only using a single region, keep this consistent for all background/occurrence objects
  929. #
  930. # k.folds <- the number of folds you want to run for cross-validation
  931. # k stops at 26 because you don't want to run 27+ fold cross-validation. The resulting data.frame becomes unwieldy.
  932. make.background.df <- function(r.stack, x.col='long', y.col='lat', time.bin='time1', region=1, k.folds=5){
  933. # ensuring that k.folds is a positive integer between [1,26]
  934. if( !is.null(k.folds) ){
  935. if( k.folds < 1){
  936. k.folds <- 1
  937. print('NOTE: Making background data.frame without any k.folds.')
  938. } else if( k.folds > 26 ){
  939. k.folds <- 26
  940. warning('k.folds has been set to 26.')
  941. } else if( k.folds%%1 != 0 ){
  942. warning('k.folds has been rounded to the nearest whole number.')
  943. k.folds <- round(k.folds)
  944. }
  945. } else {
  946. k.folds <- 1
  947. print('NOTE: Making background data.frame without any k.folds.')
  948. }
  949. # extracting the env-variables to a data.frame
  950. coords.df <- raster::sampleRandom(r.stack, ncell(r.stack), xy=TRUE, sp=FALSE, na.rm=FALSE)
  951. colnames(coords.df)[1:2] <- c(x.col, y.col)
  952. coords.df <- coords.df[complete.cases(coords.df), ]
  953. n.points <- nrow(coords.df)
  954. # making the data.frame of the name, time.bin, region, and presence columns
  955. d.cols <- as.data.frame( matrix(0, nrow=n.points, ncol=4) )
  956. d.cols[,1] <- 'Background'
  957. d.cols[,2] <- time.bin
  958. d.cols[,3] <- region
  959. colnames(d.cols) <- c('Name', 'time.bin', 'region', 'presence')
  960. # merging everything together
  961. out <- do.call('cbind', list( d.cols[,1], coords.df[,1:2], d.cols[,2:3], coords.df[,3:ncol(coords.df)], d.cols[,4] ))
  962. colnames(out)[1] <- 'Name'
  963. colnames(out)[ ncol(out) ] <- 'presence'
  964. # making the cross-validation columns
  965. if( k.folds > 1 ){
  966. ltrs <- letters[1:k.folds]
  967. # training columns
  968. train <- as.data.frame( matrix(0, nrow=n.points, ncol=k.folds) )
  969. for(i in 1:k.folds){
  970. colnames(train)[i] <- paste0('tr.', paste(ltrs[-(k.folds+1-i)], collapse='') )
  971. }
  972. # testing columns
  973. test <- as.data.frame( matrix(0, nrow=n.points, ncol=k.folds) )
  974. for(i in 1:k.folds){
  975. colnames(test)[i] <- paste0('test.', paste(ltrs[(k.folds+1-i)], collapse='') )
  976. }
  977. out <- do.call('cbind', list( out, train, test ) )
  978. }
  979. # output
  980. return(out)
  981. }
  982. # function that makes an occurrence file for each extent (time.bin and/or region) in the analysis
  983. # merging the occurrence files for every extent will create the master occurrence file
  984. # MUST have the make.kfolds function also loaded
  985. ### ARGUMENTS ###
  986. # r.stack <- a raster stack containing all the predictor variables for analysis for a given extent
  987. # if using multiple extents, ensure that all the predictor variables have the exact same name and are in the same order
  988. # if testing multiple types of variables (i.e., GCM-based vs sedimentology-based), it is ideal to seperate them into . . .
  989. # . . . those two categories before reading them into R
  990. #
  991. # taxa.df <- a data.frame of occurrence with three columns that have:
  992. # 1.) the names of the taxa you are modeling
  993. # 2.) the x-coordinates of the occurrences
  994. # 3.) the y-coordinates of the occurrences
  995. # THESE COLUMNS MUST BE IN THIS ORDER!!!
  996. # this is the same format as the SWD (species with data) format for the regular maxent.jar file
  997. #
  998. # x.col <- the column name of the x-coordinate to be put in the background/occurrence objects
  999. # this MUST be consistent for all background/occurrence objects
  1000. #
  1001. # y.col <- the column name of the y-coordinate to be put in the background/occurrence objects
  1002. # this MUST be consistent for all background/occurrence objects
  1003. #
  1004. # time.bin <- the name of the time.bin to be put in the background/occurrence objects
  1005. # if only using a single time.bin, keep this consistent for all background/occurrence objects
  1006. #
  1007. # region <- the name of the region to be put in the background/occurrence objects
  1008. # if only using a single region, keep this consistent for all background/occurrence objects
  1009. #
  1010. # k.folds <- the number of folds you want to run for cross-validation
  1011. # k stops at 26 because you don't want to run 27+ fold cross-validation. The resulting data.frame becomes unwieldy.
  1012. #
  1013. # k.seed <- value for set.seed in case you want to reproduce your exact k-fold samples in the future
  1014. # NOTE that this set.seed will apply exactly the same to every species you are modeling
  1015. #
  1016. make.occurrence.df <- function(r.stack, taxa.df, x.col='long', y.col='lat', time.bin='time1', region=1, k.folds=5, k.seed=NULL){
  1017. # ensuring that k.folds is a positive integer between [1,26]
  1018. if( !is.null(k.folds) ){
  1019. if( k.folds < 1){
  1020. k.folds <- 1
  1021. print('NOTE: Making occurrence data.frame without any k.folds.')
  1022. } else if( k.folds > 26 ){
  1023. k.folds <- 26
  1024. warning('k.folds has been set to 26.')
  1025. } else if( k.folds%%1 != 0 ){
  1026. warning('k.folds has been rounded to the nearest whole number.')
  1027. k.folds <- round(k.folds)
  1028. }
  1029. } else {
  1030. k.folds <- 1
  1031. print('NOTE: Making occurrence data.frame without any k.folds.')
  1032. }
  1033. # extracting the env-variables to a data.frame
  1034. occs.df <- raster::extract(x=r.stack, y=taxa.df[,2:3])
  1035. occs.df <- cbind(taxa.df, occs.df)
  1036. colnames(occs.df)[2:3] <- c(x.col, y.col)
  1037. occs.df <- occs.df[complete.cases(occs.df), ]
  1038. colnames(occs.df)[1] <-'Name'
  1039. n.occs <- nrow(occs.df)
  1040. # making the data.frame of the name, time.bin, region, and presence columns
  1041. d.cols <- as.data.frame( matrix(0, nrow=n.occs, ncol=3) )
  1042. d.cols[,1] <- time.bin
  1043. d.cols[,2] <- region
  1044. colnames(d.cols) <- c('time.bin', 'region', 'presence')
  1045. # merging everything together
  1046. occs.df <- do.call('cbind', list(occs.df[,1:3], d.cols[,1:2], occs.df[,4:ncol(occs.df)], d.cols[,3] ) )
  1047. colnames(occs.df)[ ncol(occs.df) ] <- 'presence'
  1048. # making the cross-validation columns
  1049. if( k.folds > 1 ){
  1050. ltrs <- letters[1:k.folds]
  1051. # training columns
  1052. train <- as.data.frame( matrix(1, nrow=n.occs, ncol=k.folds) )
  1053. for(i in 1:k.folds){
  1054. colnames(train)[i] <- paste0('tr.', paste(ltrs[-(k.folds+1-i)], collapse='') )
  1055. }
  1056. # testing columns
  1057. test <- as.data.frame( matrix(0, nrow=n.occs, ncol=k.folds) )
  1058. for(i in 1:k.folds){
  1059. colnames(test)[i] <- paste0('test.', paste(ltrs[(k.folds+1-i)], collapse='') )
  1060. }
  1061. # splitting up the occurrence data.frame by taxon, then assigning the k.folds
  1062. occs.list <- base::split(occs.df, occs.df[,1])
  1063. n.taxa <- length(occs.list)
  1064. for(i in 1:n.taxa){
  1065. # setting all taxa with < k.folds occurrences to 0's. they will later be converted to exist in all the training and testing subsets
  1066. if( nrow( occs.list[[i]] ) < k.folds ){
  1067. occs.list[[i]]$presence <- 0
  1068. } else {
  1069. # filling in cross-validation folds for taxa who have > k.folds in terms of occurrences
  1070. occs.list[[i]]$presence <- make.kfolds(occs.list[[i]], k=k.folds, seed=k.seed)
  1071. }
  1072. } # closing for(i in 1:n.taxa)
  1073. # merging all the different taxa back together
  1074. occs.df <- do.call('rbind', occs.list)
  1075. colnames(occs.df)[ ncol(occs.df) ] <- 'presence'
  1076. row.names(occs.df) <- 1:nrow(occs.df)
  1077. # assigning the k.fold parameters in occs.df
  1078. for(i in 1:nrow(occs.df) ){
  1079. # for taxa with fewer occs than k.folds
  1080. if( occs.df$presence[i] == 0 ){
  1081. # train[i,] <- 1 # train is filled with 1's by default
  1082. test[i,] <- 1
  1083. } else {
  1084. # for taxa with greater occs than k.folds
  1085. cv <- occs.df$presence[i]
  1086. train[i, (k.folds+1-cv) ] <- 0
  1087. test[i, (k.folds+1-cv) ] <- 1
  1088. }
  1089. } # closing for(i in 1:nrow(occs.df) )
  1090. out <- do.call('cbind', list( occs.df, train, test ) )
  1091. } # closing if( k.folds > 1 )
  1092. # setting all the presence rows to 1
  1093. out$presence <- 1
  1094. # output
  1095. return(out)
  1096. }
  1097. # function that reduces occurrences to one per grid cell
  1098. ### ARGUMENTS ###
  1099. ## occ.data = data.frame of the occurrence file
  1100. ## rast = raster of the entire background training extent
  1101. # there will be issues if any occs are in grid cells with NA values (i.e., outside the extent)
  1102. ## name = name of the column that has the taxa names
  1103. ## long= column name that has longitude
  1104. ## lat = column name that has latitude
  1105. ## max.dist = argument from seegSDM. distance is in map units (e.g., degrees) if the raster is projected, otherwise, it is in meters.
  1106. # if any occurrences lie JUST BARELY outside the extent, this function will assign them to the nearest gril cell . . .
  1107. # . . . inside the extent if the distance from that occurrence to the nearest cell is <= max.dist.
  1108. # otherwise, that point is ignored.
  1109. # recommended that you remove points outside the extent first. it's easier to clear up that way
  1110. ## round.to is how many decimal places to round the coordinates to
  1111. # fewer decimal plaes = faster run times
  1112. # nearestLand function extracted from seegSDM as that package doesn't appear to exist for more versions (> 3.6.2) of R
  1113. # this version of nearestLand is from seegSDM version 0.1-9
  1114. seegSDM_nearestLand <- function (points, raster, max_distance) {
  1115. nearest <- function(lis, raster) {
  1116. neighbours <- matrix(lis[[1]], ncol = 2)
  1117. point <- lis[[2]]
  1118. land <- !is.na(neighbours[, 2])
  1119. if (!any(land)) {
  1120. return(c(NA, NA))
  1121. } else {
  1122. coords <- xyFromCell(raster, neighbours[land, 1])
  1123. if (nrow(coords) == 1) {
  1124. return(coords[1, ])
  1125. }
  1126. dists <- sqrt((coords[, 1] - point[1])^2 + (coords[, 2] - point[2])^2)
  1127. return(coords[which.min(dists), ])
  1128. } # ending else
  1129. } # ending nearest
  1130. neighbour_list <- extract(raster, points, buffer = max_distance, cellnumbers = TRUE)
  1131. neighbour_list <- lapply(1:nrow(points), function(i) {
  1132. list(neighbours = neighbour_list[[i]], point = as.numeric(points[i, ]))
  1133. })
  1134. return(t(sapply(neighbour_list, nearest, raster)))
  1135. }
  1136. #
  1137. one.occ.per.grid.cell.no.SEEG <- function(occ.data, rast, name = 'species', long = 'long', lat = 'lat', max.dist = .0833, round.to = 5) {# I CHANGED MAX DIST TO .083 because 5 arc minutes?
  1138. require(raster)
  1139. occ.mat <- as.matrix(occ.data[,c(long, lat)])
  1140. occ.mat <- round(occ.mat, digits = round.to)
  1141. moved <- seegSDM_nearestLand(occ.mat, raster=rast, max_distance=max.dist) # centers occ. points within the grid cell they occur in
  1142. moved <- as.data.frame(moved)
  1143. moved <- cbind(occ.data[,name], moved) # bind names and the paleo-longitudes
  1144. colnames(moved) <- c(name, 'long.thin', 'lat.thin')
  1145. moved <- unique(moved) # returns only one occurrence per entity per grid
  1146. numbs <- as.numeric(row.names(moved)) # row numbers of the thinned data
  1147. out <- occ.data[numbs,] # thinning the original data with the rows of the thinned data
  1148. return(out)
  1149. }
  1150. #################&&&&&&&&&&&&&&&&&&&&&############MAKE MASTER#################
  1151. #################### ACER PRES MASTER
  1152. # reading in the occurrence file
  1153. Pres.occs <- read.csv('AcroporaCervicornisPresent.csv', header = TRUE, stringsAsFactors=FALSE, fileEncoding="latin1")
  1154. Holo.occs <- read.csv('AcroporaCervicornisHolocene.csv', header = TRUE, stringsAsFactors=FALSE, fileEncoding="latin1")
  1155. Pres.occs <- Pres.occs[,-1]
  1156. Holo.occs <- Holo.occs[,-1]
  1157. head(Pres.occs)
  1158. head(Holo.occs)
  1159. identical(colnames(Pres.occs), colnames(Holo.occs))
  1160. nrow(Pres.occs)
  1161. nrow(Holo.occs)
  1162. Pres.occs[,1:2] <- round(Pres.occs[,1:2], 3)
  1163. Holo.occs[,1:2] <- round(Holo.occs[,1:2], 3)
  1164. #assigning wgs84 projection if not already assigned in layers
  1165. wgs1984 <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
  1166. ### reading in the raster files (if they are geotiff, then change below to '\\.tif$'); all layers must be the same file type
  1167. ## present+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1168. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Bio-Oracle Future/MASKED/present")
  1169. Prescomp.files <- list.files(path='/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Bio-Oracle Future/MASKED/present', pattern='\\.tif$')
  1170. Prescomp.files
  1171. # make sure order of how e-layers are read in is the same for each analysis extent (i.e., time bins or spatial areas)
  1172. #Pres.files <- Pres.files[ c(1,2,3,4,5) ]
  1173. Prescomp.rasters <- raster::stack( Prescomp.files)
  1174. # optionally assigning a crs if one isn't provided
  1175. crs(Prescomp.rasters) <- wgs1984
  1176. names(Prescomp.rasters)
  1177. # ## holocene+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1178. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/HOLOMASKED")
  1179. Holo.files <- list.files(path='/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/HOLOMASKED', pattern='\\.tif$')
  1180. Holo.files
  1181. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1182. Holo.rasters <- raster::stack( Holo.files)
  1183. Holo.rasters <- Holo.rasters/100
  1184. # optionally assigning a crs if one isn't provided
  1185. crs(Holo.rasters) <- wgs1984
  1186. names(Holo.rasters)
  1187. # re-naming the names of rasters if you want to
  1188. names(Prescomp.rasters) <- c( "maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1189. names(Holo.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1190. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1191. identical( names(Prescomp.rasters), names(Holo.rasters) )
  1192. ######################future 2050 RCP45+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1193. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452050")
  1194. RCP452050.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452050", pattern='\\.tif$')
  1195. RCP452050.files
  1196. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1197. RCP452050.rasters <- raster::stack( RCP452050.files)
  1198. # optionally assigning a crs if one isn't provided
  1199. crs(RCP452050.rasters) <- wgs1984
  1200. names(RCP452050.rasters)
  1201. # re-naming the names of turo.rasters if you want to
  1202. names(RCP452050.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1203. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1204. identical( names(Holo.rasters), names(RCP452050.rasters) )
  1205. # #############################future 2050 RCP85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1206. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852050")
  1207. RCP852050.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852050", pattern='\\.tif$')
  1208. RCP852050.files
  1209. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1210. RCP852050.rasters <- raster::stack( RCP852050.files)
  1211. # optionally assigning a crs if one isn't provided
  1212. crs(RCP852050.rasters) <- wgs1984
  1213. names(RCP852050.rasters)
  1214. # re-naming the names of turo.rasters if you want to
  1215. names(RCP852050.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1216. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1217. identical( names(Holo.rasters), names(RCP852050.rasters) )
  1218. # ###############future 2100 RCP45+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1219. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452100")
  1220. RCP452100.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452100", pattern='\\.tif$')
  1221. RCP452100.files
  1222. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1223. RCP452100.rasters <- raster::stack( RCP452100.files)
  1224. # optionally assigning a crs if one isn't provided
  1225. crs(RCP452100.rasters) <- wgs1984
  1226. names(RCP452100.rasters)
  1227. names(RCP452100.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp")
  1228. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1229. identical( names(Holo.rasters), names(RCP452100.rasters) )
  1230. # #################future 2100 RCP85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1231. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852100")
  1232. RCP852100.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852100", pattern='\\.tif$')
  1233. RCP852100.files
  1234. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1235. RCP852100.rasters <- raster::stack( RCP852100.files)
  1236. # optionally assigning a crs if one isn't provided
  1237. crs(RCP852100.rasters) <- wgs1984
  1238. names(RCP852100.rasters)
  1239. names(RCP852100.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp")
  1240. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1241. identical( names(Holo.rasters), names(RCP852100.rasters) )
  1242. # making the background files
  1243. Prescomp.back <- make.background.df(r.stack=Prescomp.rasters, x.col='long', y.col='lat', time.bin='Present', region='Caribbean')
  1244. Holo.back <- make.background.df(r.stack=Holo.rasters, x.col='long', y.col='lat', time.bin='Holocene', region='Caribbean')
  1245. RCP452050.back <- make.background.df(r.stack=RCP452050.rasters, x.col='long', y.col='lat', time.bin='RCP452050', region='Caribbean')
  1246. RCP852050.back <- make.background.df(r.stack=RCP852050.rasters, x.col='long', y.col='lat', time.bin='RCP852050', region='Caribbean')
  1247. RCP452100.back <- make.background.df(r.stack=RCP452100.rasters, x.col='long', y.col='lat', time.bin='RCP452100', region='Caribbean')
  1248. RCP852100.back <- make.background.df(r.stack=RCP852100.rasters, x.col='long', y.col='lat', time.bin='RCP852100', region='Caribbean')
  1249. #spatial thinning
  1250. Pres.occs.thin <- one.occ.per.grid.cell.no.SEEG(occ.data = Pres.occs, rast = Prescomp.rasters[[2]], name = "name", long = "long", lat = "lat")
  1251. Holo.occs.thin <- one.occ.per.grid.cell.no.SEEG(occ.data = Holo.occs, rast = Holo.rasters[[2]], name = "name", long = "long", lat = "lat")
  1252. #how many occurrences are there - compare to original before spatial thinning to see if less
  1253. nrow(Pres.occs.thin)
  1254. nrow(Holo.occs.thin)
  1255. #look at new spatially thinned dataframe
  1256. View(Pres.occs.thin)
  1257. # making the occurrence files
  1258. # c(8,2,1) = (GENUS, Longitude, Latitude)
  1259. Pres.occs.df <- make.occurrence.df(r.stack=Prescomp.rasters, taxa.df=Pres.occs.thin[,c(3,1,2)], #I think this bit is reorganizing the columns and I made it 3 not 8 and switched 2 1 for 1 2
  1260. x.col='long', y.col='lat', time.bin='Present', region='Caribbean')
  1261. Holo.occs.df <- make.occurrence.df(r.stack=Holo.rasters, taxa.df=Holo.occs.thin[,c(3,1,2)],
  1262. x.col='long', y.col='lat', time.bin='Holocene', region='Caribbean')
  1263. # checking to see if everything has identical column names for your different extents
  1264. identical( colnames(Prescomp.back), colnames(Holo.back) )
  1265. identical( colnames(Pres.occs.df), colnames(Holo.occs.df) )
  1266. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/ACERV/masked/Master_files_acerv_add_mask")
  1267. masterall.background <- do.call('rbind', list(Prescomp.back, Holo.back,
  1268. RCP452050.back,RCP852050.back,
  1269. RCP452100.back, RCP852100.back
  1270. ) )
  1271. write.csv(masterall.background, 'masterall.background.csv', row.names = FALSE)
  1272. masterall.occs <- do.call('rbind', list(Pres.occs, Holo.occs) )
  1273. View(masterall.occs)
  1274. write.csv(masterall.occs, 'masterall.occs.csv', row.names = FALSE)
  1275. masterpres.occs <- Pres.occs.df
  1276. write.csv(masterpres.occs, 'masterpres.occs.csv', row.names = FALSE)
  1277. masterholo.occs <- Holo.occs.df
  1278. write.csv(masterholo.occs, 'masterholo.occs.csv', row.names = FALSE)
  1279. #################################### ACER HOLO MASTER same code but with area masked for cuba jamaica and hispanola
  1280. #################################### APAL PRES MASTER
  1281. # reading in the occurrence file
  1282. Pres.occs <- read.csv('AcroporaPalmataPresent2.csv', header = TRUE, stringsAsFactors=FALSE, fileEncoding="latin1")
  1283. Holo.occs <- read.csv('AcroporaPalmataHolocene.csv', header = TRUE, stringsAsFactors=FALSE, fileEncoding="latin1")
  1284. Pres.occs <- Pres.occs[,-1]
  1285. Holo.occs <- Holo.occs[,-1]
  1286. head(Pres.occs)
  1287. head(Holo.occs)
  1288. identical(colnames(Pres.occs), colnames(Holo.occs))
  1289. nrow(Pres.occs)
  1290. nrow(Holo.occs)
  1291. Pres.occs[,1:2] <- round(Pres.occs[,1:2], 3)
  1292. Holo.occs[,1:2] <- round(Holo.occs[,1:2], 3)
  1293. ################################################################################################################################################
  1294. #assignin wgs84 projection if not already assigned in layers
  1295. wgs1984 <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
  1296. ### reading in the raster files (if they are geotiff, then change below to '\\.tif$'); all layers must be the same file type
  1297. ## present+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1298. Prescomp.files <- list.files(path='/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Bio-Oracle Future/MASKED/present', pattern='\\.tif$')
  1299. Prescomp.files
  1300. # re-ordering any files
  1301. # make sure order of how e-layers are read in is the same for each analysis extent (i.e., time bins or spatial areas)
  1302. #Pres.files <- Pres.files[ c(1,2,3,4,5) ]
  1303. Prescomp.rasters <- raster::stack( Prescomp.files)
  1304. # optionally assigning a crs if one isn't provided
  1305. crs(Prescomp.rasters) <- wgs1984
  1306. names(Prescomp.rasters)
  1307. # ## holocene+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1308. Holo.files <- list.files(path='/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam', pattern='\\.tif$')
  1309. Holo.files
  1310. #reorder
  1311. Holo.files <- Holo.files[ c(1,3,2,4) ]
  1312. Holo.files
  1313. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1314. Holo.rasters <- raster::stack( Holo.files)
  1315. Holo.rasters <- Holo.rasters/100
  1316. # optionally assigning a crs if one isn't provided
  1317. crs(Holo.rasters) <- wgs1984
  1318. names(Holo.rasters)
  1319. names(Prescomp.rasters) <- c( "maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1320. names(Holo.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1321. # ## holocene+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1322. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/HOLOMASKED")
  1323. Holo2.files <- list.files(path='/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/HOLOMASKED', pattern='\\.tif$')
  1324. Holo2.files
  1325. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1326. Holo2.rasters <- raster::stack( Holo2.files)
  1327. Holo2.rasters <- Holo2.rasters/100
  1328. # optionally assigning a crs if one isn't provided
  1329. crs(Holo2.rasters) <- wgs1984
  1330. names(Holo2.rasters)
  1331. # re-naming the names of rasters if you want to
  1332. names(Prescomp.rasters) <- c( "maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1333. names(Holo2.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1334. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1335. identical( names(Prescomp.rasters), names(Holo.rasters) )
  1336. #
  1337. ######################future 2050 RCP45+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1338. RCP452050.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452050", pattern='\\.tif$')
  1339. RCP452050.files
  1340. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1341. RCP452050.rasters <- raster::stack( RCP452050.files)
  1342. # optionally assigning a crs if one isn't provided
  1343. crs(RCP452050.rasters) <- wgs1984
  1344. names(RCP452050.rasters)
  1345. # re-naming the names of turo.rasters if you want to
  1346. names(RCP452050.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1347. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1348. identical( names(Holo.rasters), names(RCP452050.rasters) )
  1349. #
  1350. # #############################future 2050 RCP85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1351. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852050")
  1352. RCP852050.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852050", pattern='\\.tif$')
  1353. RCP852050.files
  1354. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1355. RCP852050.rasters <- raster::stack( RCP852050.files)
  1356. # optionally assigning a crs if one isn't provided
  1357. crs(RCP852050.rasters) <- wgs1984
  1358. names(RCP852050.rasters)
  1359. # re-naming the names of turo.rasters if you want to
  1360. names(RCP852050.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1361. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1362. identical( names(Holo.rasters), names(RCP852050.rasters) )
  1363. # ###############future 2100 RCP45+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1364. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452100")
  1365. RCP452100.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452100", pattern='\\.tif$')
  1366. RCP452100.files
  1367. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1368. RCP452100.rasters <- raster::stack( RCP452100.files)
  1369. # optionally assigning a crs if one isn't provided
  1370. crs(RCP452100.rasters) <- wgs1984
  1371. names(RCP452100.rasters)
  1372. names(RCP452100.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp")
  1373. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1374. identical( names(Holo.rasters), names(RCP452100.rasters) )
  1375. # #################future 2100 RCP85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1376. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852100")
  1377. RCP852100.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852100", pattern='\\.tif$')
  1378. RCP852100.files
  1379. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1380. RCP852100.rasters <- raster::stack( RCP852100.files)
  1381. # optionally assigning a crs if one isn't provided
  1382. crs(RCP852100.rasters) <- wgs1984
  1383. names(RCP852100.rasters)
  1384. names(RCP852100.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp")
  1385. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1386. identical( names(Holo.rasters), names(RCP852100.rasters) )
  1387. #
  1388. #
  1389. # making the background files
  1390. Prescomp.back <- make.background.df(r.stack=Prescomp.rasters, x.col='long', y.col='lat', time.bin='Present', region='Caribbean')
  1391. Holo.back <- make.background.df(r.stack=Holo.rasters, x.col='long', y.col='lat', time.bin='Holocene', region='Caribbean')
  1392. Holo2.back <- make.background.df(r.stack=Holo2.rasters, x.col='long', y.col='lat', time.bin='Holocene2', region='Caribbean')
  1393. #
  1394. RCP452050.back <- make.background.df(r.stack=RCP452050.rasters, x.col='long', y.col='lat', time.bin='RCP452050', region='Caribbean')
  1395. #
  1396. RCP852050.back <- make.background.df(r.stack=RCP852050.rasters, x.col='long', y.col='lat', time.bin='RCP852050', region='Caribbean')
  1397. #
  1398. RCP452100.back <- make.background.df(r.stack=RCP452100.rasters, x.col='long', y.col='lat', time.bin='RCP452100', region='Caribbean')
  1399. #
  1400. RCP852100.back <- make.background.df(r.stack=RCP852100.rasters, x.col='long', y.col='lat', time.bin='RCP852100', region='Caribbean')
  1401. #spatial thinning
  1402. Pres.occs.thin <- one.occ.per.grid.cell.no.SEEG(occ.data = Pres.occs, rast = Prescomp.rasters[[2]], name = "name", long = "long", lat = "lat")
  1403. Holo.occs.thin <- one.occ.per.grid.cell.no.SEEG(occ.data = Holo.occs, rast = Holo.rasters[[2]], name = "name", long = "long", lat = "lat")
  1404. #how many occurrences are there - compare to original before spatial thinning to see if less
  1405. nrow(Pres.occs.thin)
  1406. nrow(Holo.occs.thin)
  1407. #look at new spatially thinned dataframe
  1408. View(Pres.occs.thin)
  1409. # making the occurrence files
  1410. # c(8,2,1) = (GENUS, Longitude, Latitude)
  1411. Pres.occs.df <- make.occurrence.df(r.stack=Prescomp.rasters, taxa.df=Pres.occs.thin[,c(3,1,2)], #I think this bit is reorganizing the columns and I made it 3 not 8 and switched 2 1 for 1 2
  1412. x.col='long', y.col='lat', time.bin='Present', region='Caribbean')
  1413. Holo.occs.df <- make.occurrence.df(r.stack=Holo.rasters, taxa.df=Holo.occs.thin[,c(3,1,2)],
  1414. x.col='long', y.col='lat', time.bin='Holocene', region='Caribbean')
  1415. # checking to see if everything has identical column names for your different extents
  1416. identical( colnames(Prescomp.back), colnames(Holo.back) )
  1417. identical( colnames(Pres.occs.df), colnames(Holo.occs.df) )
  1418. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/maskedtwice/Master_files_apal_add_mask")
  1419. # merging together the files
  1420. masterall.background <- do.call('rbind', list(Prescomp.back, Holo.back, Holo2.back,
  1421. RCP452050.back,RCP852050.back,
  1422. RCP452100.back, RCP852100.back
  1423. ) )
  1424. write.csv(masterall.background, 'masterall.background.csv', row.names = FALSE)
  1425. masterall.occs <- do.call('rbind', list(Pres.occs, Holo.occs) )
  1426. View(masterall.occs)
  1427. write.csv(masterall.occs, 'masterall.occs.csv', row.names = FALSE)
  1428. masterpres.occs <- Pres.occs.df
  1429. write.csv(masterpres.occs, 'masterpres.occs.csv', row.names = FALSE)
  1430. masterholo.occs <- Holo.occs.df
  1431. write.csv(masterholo.occs, 'masterholo.occs.csv', row.names = FALSE)
  1432. ########################### APAL HOLO MASTER same but with masked background
  1433. #################### CNAT PRES MASTER
  1434. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/CNAT/Cnatans")
  1435. # reading in the occurrence file
  1436. Pres.occs <- read.csv('CnatansPresent.csv', header = TRUE, stringsAsFactors=FALSE, fileEncoding="latin1")
  1437. Holo.occs <- read.csv('CnatansHolocene.csv', header = TRUE, stringsAsFactors=FALSE, fileEncoding="latin1")
  1438. Pres.occs <- Pres.occs[,-1]
  1439. Holo.occs <- Holo.occs[,-1]
  1440. head(Pres.occs)
  1441. head(Holo.occs)
  1442. identical(colnames(Pres.occs), colnames(Holo.occs))
  1443. nrow(Pres.occs)
  1444. nrow(Holo.occs)
  1445. Pres.occs[,1:2] <- round(Pres.occs[,1:2], 3)
  1446. Holo.occs[,1:2] <- round(Holo.occs[,1:2], 3)
  1447. ################################################################################################################################################
  1448. #assignin wgs84 projection if not already assigned in layers
  1449. wgs1984 <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
  1450. ### reading in the raster files (if they are geotiff, then change below to '\\.tif$'); all layers must be the same file type
  1451. ## present+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1452. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Bio-Oracle Future/MASKED/present")
  1453. Prescomp.files <- list.files(path='/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Bio-Oracle Future/MASKED/present', pattern='\\.tif$')
  1454. Prescomp.files
  1455. Prescomp.rasters <- raster::stack( Prescomp.files)
  1456. # optionally assigning a crs if one isn't provided
  1457. crs(Prescomp.rasters) <- wgs1984
  1458. names(Prescomp.rasters)
  1459. # ## holocene+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1460. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/HOLOMASKED")
  1461. Holo.files <- list.files(path='/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/HOLOMASKED', pattern='\\.tif$')
  1462. Holo.files
  1463. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1464. Holo.rasters <- raster::stack( Holo.files)
  1465. #scaling the holocene raster
  1466. Holo.rasters <- Holo.rasters/100
  1467. # optionally assigning a crs if one isn't provided
  1468. crs(Holo.rasters) <- wgs1984
  1469. names(Holo.rasters)
  1470. # re-naming the names of rasters if you want to
  1471. names(Prescomp.rasters) <- c( "maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1472. names(Holo.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1473. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1474. identical( names(Prescomp.rasters), names(Holo.rasters) )
  1475. ######################future 2050 RCP45+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1476. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452050")
  1477. RCP452050.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452050", pattern='\\.tif$')
  1478. RCP452050.files
  1479. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1480. RCP452050.rasters <- raster::stack( RCP452050.files)
  1481. # optionally assigning a crs if one isn't provided
  1482. crs(RCP452050.rasters) <- wgs1984
  1483. names(RCP452050.rasters)
  1484. # re-naming the names of turo.rasters if you want to
  1485. names(RCP452050.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1486. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1487. identical( names(Holo.rasters), names(RCP452050.rasters) )
  1488. # #############################future 2050 RCP85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1489. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852050")
  1490. RCP852050.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852050", pattern='\\.tif$')
  1491. RCP852050.files
  1492. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1493. RCP852050.rasters <- raster::stack( RCP852050.files)
  1494. # optionally assigning a crs if one isn't provided
  1495. crs(RCP852050.rasters) <- wgs1984
  1496. names(RCP852050.rasters)
  1497. # re-naming the names of turo.rasters if you want to
  1498. names(RCP852050.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1499. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1500. identical( names(Holo.rasters), names(RCP852050.rasters) )
  1501. #
  1502. # ###############future 2100 RCP45+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1503. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452100")
  1504. RCP452100.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452100", pattern='\\.tif$')
  1505. RCP452100.files
  1506. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1507. RCP452100.rasters <- raster::stack( RCP452100.files)
  1508. # optionally assigning a crs if one isn't provided
  1509. crs(RCP452100.rasters) <- wgs1984
  1510. names(RCP452100.rasters)
  1511. names(RCP452100.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp")
  1512. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1513. identical( names(Holo.rasters), names(RCP452100.rasters) )
  1514. #
  1515. # #################future 2100 RCP85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1516. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852100")
  1517. RCP852100.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852100", pattern='\\.tif$')
  1518. RCP852100.files
  1519. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1520. RCP852100.rasters <- raster::stack( RCP852100.files)
  1521. # optionally assigning a crs if one isn't provided
  1522. crs(RCP852100.rasters) <- wgs1984
  1523. names(RCP852100.rasters)
  1524. names(RCP852100.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp")
  1525. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1526. identical( names(Holo.rasters), names(RCP852100.rasters) )
  1527. #
  1528. #
  1529. # making the background files
  1530. Prescomp.back <- make.background.df(r.stack=Prescomp.rasters, x.col='long', y.col='lat', time.bin='Present', region='Caribbean')
  1531. Holo.back <- make.background.df(r.stack=Holo.rasters, x.col='long', y.col='lat', time.bin='Holocene', region='Caribbean')
  1532. RCP452050.back <- make.background.df(r.stack=RCP452050.rasters, x.col='long', y.col='lat', time.bin='RCP452050', region='Caribbean')
  1533. RCP852050.back <- make.background.df(r.stack=RCP852050.rasters, x.col='long', y.col='lat', time.bin='RCP852050', region='Caribbean')
  1534. RCP452100.back <- make.background.df(r.stack=RCP452100.rasters, x.col='long', y.col='lat', time.bin='RCP452100', region='Caribbean')
  1535. RCP852100.back <- make.background.df(r.stack=RCP852100.rasters, x.col='long', y.col='lat', time.bin='RCP852100', region='Caribbean')
  1536. #spatial thinning
  1537. Pres.occs.thin <- one.occ.per.grid.cell.no.SEEG(occ.data = Pres.occs, rast = Prescomp.rasters[[2]], name = "name", long = "long", lat = "lat")
  1538. Holo.occs.thin <- one.occ.per.grid.cell.no.SEEG(occ.data = Holo.occs, rast = Holo.rasters[[2]], name = "name", long = "long", lat = "lat")
  1539. #how many occurrences are there - compare to original before spatial thinning to see if less
  1540. nrow(Pres.occs.thin)
  1541. nrow(Holo.occs.thin)
  1542. #look at new spatially thinned dataframe
  1543. View(Pres.occs.thin)
  1544. # making the occurrence files
  1545. # c(8,2,1) = (GENUS, Longitude, Latitude)
  1546. Pres.occs.df <- make.occurrence.df(r.stack=Prescomp.rasters, taxa.df=Pres.occs.thin[,c(3,1,2)], #I think this bit is reorganizing the columns and I made it 3 not 8 and switched 2 1 for 1 2
  1547. x.col='long', y.col='lat', time.bin='Present', region='Caribbean')
  1548. Holo.occs.df <- make.occurrence.df(r.stack=Holo.rasters, taxa.df=Holo.occs.thin[,c(3,1,2)],
  1549. x.col='long', y.col='lat', time.bin='Holocene', region='Caribbean')
  1550. # checking to see if everything has identical column names for your different extents
  1551. identical( colnames(Prescomp.back), colnames(Holo.back) )
  1552. identical( colnames(Pres.occs.df), colnames(Holo.occs.df) )
  1553. identical( colnames(Prescomp.back), colnames(Holo.occs.df) )
  1554. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/CNAT/masked/Master_files_cnat_add_mask")
  1555. # merging together the files
  1556. masterall.background <- do.call('rbind', list(Prescomp.back, Holo.back,
  1557. RCP452050.back,RCP852050.back,
  1558. RCP452100.back, RCP852100.back) )
  1559. write.csv(masterall.background, 'masterall.background.csv', row.names = FALSE)
  1560. masterall.occs <- do.call('rbind', list(Pres.occs, Holo.occs) )#LGM.occs
  1561. View(masterall.occs)
  1562. write.csv(masterall.occs, 'masterall.occs.csv', row.names = FALSE)
  1563. masterpres.occs <- Pres.occs.df
  1564. write.csv(masterpres.occs, 'masterpres.occs.csv', row.names = FALSE)
  1565. masterholo.occs <- Holo.occs.df
  1566. write.csv(masterholo.occs, 'masterholo.occs.csv', row.names = FALSE)
  1567. #################### CNAT HOLO MASTER same with masked extent
  1568. #################### PAST PRES MASTER
  1569. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/PAST/Pasteroides")
  1570. # reading in the occurrence file
  1571. Pres.occs <- read.csv('PoritesAsteroidesPresent.csv', header = TRUE, stringsAsFactors=FALSE, fileEncoding="latin1")
  1572. Holo.occs <- read.csv('PoritesAsteroidesHolocene.csv', header = TRUE, stringsAsFactors=FALSE, fileEncoding="latin1")
  1573. Pres.occs <- Pres.occs[,-1]
  1574. Holo.occs <- Holo.occs[,-1]
  1575. head(Pres.occs)
  1576. head(Holo.occs)
  1577. identical(colnames(Pres.occs), colnames(Holo.occs))
  1578. nrow(Pres.occs)
  1579. nrow(Holo.occs)
  1580. Pres.occs[,1:2] <- round(Pres.occs[,1:2], 3)
  1581. Holo.occs[,1:2] <- round(Holo.occs[,1:2], 3)
  1582. ################################################################################################################################################
  1583. #assignin wgs84 projection if not already assigned in layers
  1584. wgs1984 <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
  1585. ### reading in the raster files (if they are geotiff, then change below to '\\.tif$'); all layers must be the same file type
  1586. ## present+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1587. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Bio-Oracle Future/MASKED/present")
  1588. Prescomp.files <- list.files(path='/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Bio-Oracle Future/MASKED/present', pattern='\\.tif$')
  1589. Prescomp.files
  1590. # re-ordering any files
  1591. # make sure order of how e-layers are read in is the same for each analysis extent (i.e., time bins or spatial areas)
  1592. #Pres.files <- Pres.files[ c(1,2,3,4,5) ]
  1593. Prescomp.rasters <- raster::stack( Prescomp.files)
  1594. # optionally assigning a crs if one isn't provided
  1595. crs(Prescomp.rasters) <- wgs1984
  1596. names(Prescomp.rasters)
  1597. # ## holocene+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1598. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/HOLOMASKED")
  1599. Holo.files <- list.files(path='/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/HOLOMASKED', pattern='\\.tif$')
  1600. Holo.files
  1601. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1602. Holo.rasters <- raster::stack( Holo.files)
  1603. Holo.rasters <- Holo.rasters/100
  1604. # optionally assigning a crs if one isn't provided
  1605. crs(Holo.rasters) <- wgs1984
  1606. names(Holo.rasters)
  1607. # re-naming the names of rasters if you want to
  1608. names(Prescomp.rasters) <- c( "maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1609. names(Holo.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1610. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1611. identical( names(Prescomp.rasters), names(Holo.rasters) )
  1612. ######################future 2050 RCP45+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1613. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452050")
  1614. RCP452050.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452050", pattern='\\.tif$')
  1615. RCP452050.files
  1616. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1617. RCP452050.rasters <- raster::stack( RCP452050.files)
  1618. # optionally assigning a crs if one isn't provided
  1619. crs(RCP452050.rasters) <- wgs1984
  1620. names(RCP452050.rasters)
  1621. # re-naming the names of turo.rasters if you want to
  1622. names(RCP452050.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1623. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1624. identical( names(Holo.rasters), names(RCP452050.rasters) )
  1625. # #############################future 2050 RCP85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1626. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852050")
  1627. RCP852050.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852050", pattern='\\.tif$')
  1628. RCP852050.files
  1629. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1630. RCP852050.rasters <- raster::stack( RCP852050.files)
  1631. # optionally assigning a crs if one isn't provided
  1632. crs(RCP852050.rasters) <- wgs1984
  1633. names(RCP852050.rasters)
  1634. # re-naming the names of turo.rasters if you want to
  1635. names(RCP852050.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp" )
  1636. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1637. identical( names(Holo.rasters), names(RCP852050.rasters) )
  1638. # ###############future 2100 RCP45+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1639. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452100")
  1640. RCP452100.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP452100", pattern='\\.tif$')
  1641. RCP452100.files
  1642. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1643. RCP452100.rasters <- raster::stack( RCP452100.files)
  1644. # optionally assigning a crs if one isn't provided
  1645. crs(RCP452100.rasters) <- wgs1984
  1646. names(RCP452100.rasters)
  1647. names(RCP452100.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp")
  1648. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1649. identical( names(Holo.rasters), names(RCP452100.rasters) )
  1650. # #################future 2100 RCP85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1651. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852100")
  1652. RCP852100.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle future/MASKED/RCP852100", pattern='\\.tif$')
  1653. RCP852100.files
  1654. #when loading things as a raster::stack, must have the same file extent - nrows, ncol, ncell, nlayers, pixel size
  1655. RCP852100.rasters <- raster::stack( RCP852100.files)
  1656. # optionally assigning a crs if one isn't provided
  1657. crs(RCP852100.rasters) <- wgs1984
  1658. names(RCP852100.rasters)
  1659. names(RCP852100.rasters) <- c("maxsalinity", "maxtemp", "rangesalinity", "rangetemp")
  1660. #make sure e-layer names of each extent (time bin or region) is the same name and same order; if it is, will say TRUE
  1661. identical( names(Holo.rasters), names(RCP852100.rasters) )
  1662. #
  1663. #
  1664. # making the background files
  1665. Prescomp.back <- make.background.df(r.stack=Prescomp.rasters, x.col='long', y.col='lat', time.bin='Present', region='Caribbean')
  1666. Holo.back <- make.background.df(r.stack=Holo.rasters, x.col='long', y.col='lat', time.bin='Holocene', region='Caribbean')
  1667. RCP452050.back <- make.background.df(r.stack=RCP452050.rasters, x.col='long', y.col='lat', time.bin='RCP452050', region='Caribbean')
  1668. RCP852050.back <- make.background.df(r.stack=RCP852050.rasters, x.col='long', y.col='lat', time.bin='RCP852050', region='Caribbean')
  1669. RCP452100.back <- make.background.df(r.stack=RCP452100.rasters, x.col='long', y.col='lat', time.bin='RCP452100', region='Caribbean')
  1670. RCP852100.back <- make.background.df(r.stack=RCP852100.rasters, x.col='long', y.col='lat', time.bin='RCP852100', region='Caribbean')
  1671. #spatial thinning
  1672. Pres.occs.thin <- one.occ.per.grid.cell.no.SEEG(occ.data = Pres.occs, rast = Prescomp.rasters[[2]], name = "name", long = "long", lat = "lat")
  1673. Holo.occs.thin <- one.occ.per.grid.cell.no.SEEG(occ.data = Holo.occs, rast = Holo.rasters[[2]], name = "name", long = "long", lat = "lat")
  1674. #how many occurrences are there - compare to original before spatial thinning to see if less
  1675. nrow(Pres.occs.thin)
  1676. nrow(Holo.occs.thin)
  1677. #look at new spatially thinned dataframe
  1678. View(Pres.occs.thin)
  1679. # making the occurrence files
  1680. # c(8,2,1) = (GENUS, Longitude, Latitude)
  1681. Pres.occs.df <- make.occurrence.df(r.stack=Prescomp.rasters, taxa.df=Pres.occs.thin[,c(3,1,2)], #I think this bit is reorganizing the columns and I made it 3 not 8 and switched 2 1 for 1 2
  1682. x.col='long', y.col='lat', time.bin='Present', region='Caribbean')
  1683. Holo.occs.df <- make.occurrence.df(r.stack=Holo.rasters, taxa.df=Holo.occs.thin[,c(3,1,2)],
  1684. x.col='long', y.col='lat', time.bin='Holocene', region='Caribbean')
  1685. # checking to see if everything has identical column names for your different extents
  1686. identical( colnames(Prescomp.back), colnames(Holo.back) )
  1687. identical( colnames(Pres.occs.df), colnames(Holo.occs.df) )
  1688. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/PAST/masked/Master_files_past_add_mask")
  1689. # merging together the files
  1690. masterall.background <- do.call('rbind', list(Prescomp.back, Holo.back,
  1691. RCP452050.back,RCP852050.back,
  1692. RCP452100.back, RCP852100.back) )
  1693. write.csv(masterall.background, 'masterall.background.csv', row.names = FALSE)
  1694. masterall.occs <- do.call('rbind', list(Pres.occs, Holo.occs) )
  1695. View(masterall.occs)
  1696. write.csv(masterall.occs, 'masterall.occs.csv', row.names = FALSE)
  1697. masterpres.occs <- Pres.occs.df
  1698. write.csv(masterpres.occs, 'masterpres.occs.csv', row.names = FALSE)
  1699. masterholo.occs <- Holo.occs.df
  1700. write.csv(masterholo.occs, 'masterholo.occs.csv', row.names = FALSE)
  1701. #################### PAST HOLO MASTER same with masked extent
  1702. #################&&&&&&&&&&&&&&&&&&&&&############ECOSPAT#################
  1703. ####################################### ACER ECOSPAT ###########################
  1704. #### MODEL COMPARISON ####
  1705. #need cleaned occurrence data and environmental data rasters
  1706. ## Read in shapefiles of cleaned occ data ##
  1707. ########################occurrence data######################
  1708. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/ACERV/masked/maskedtwice/Master_files_acerv_add_mask")
  1709. AcervPres = read.csv("masterpres.occs.csv")
  1710. AcervPres = as(AcervPres,'data.frame')
  1711. AcervHolo = read.csv("masterholo.occs.csv")
  1712. AcervHolo = as(AcervHolo,'data.frame')
  1713. #convert to dataframe for use in ecospat
  1714. ###################environmental###################
  1715. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present")
  1716. # Upload basic rasters for First interval (Present)
  1717. Prescomp.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present", pattern='\\.tif$')
  1718. Prescomp.files
  1719. maxsalinitypres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/maxsalinity.tif")
  1720. maxsalinitypres
  1721. maxtemppres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/maxtemp.tif")
  1722. maxtemppres
  1723. rangesalinitypres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/rangesalinity.tif")
  1724. rangesalinitypres
  1725. rangetemppres <- raster ("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/rangetemp.tif")
  1726. rangetemppres
  1727. # make sure order of how e-layers are read in is the same for each analysis extent (i.e., time bins or spatial areas)
  1728. Prescomp.rasters <- raster::stack(c(maxsalinitypres, maxtemppres, rangesalinitypres, rangetemppres))
  1729. wgs1984 <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
  1730. # optionally assigning a crs if one isn't provided
  1731. crs(Prescomp.rasters) <- wgs1984
  1732. names(Prescomp.rasters)
  1733. names(Prescomp.rasters) <- c('maxsalinity', 'maxtemp', 'rangesalinity', 'rangetemp')
  1734. #Upload basic rasters for Second interval (Holocene)
  1735. ## holocene+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1736. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam")
  1737. Holo.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam", pattern='\\.tif$')
  1738. #scaling holocene layers
  1739. maxsalinityholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/salmaxmask2.tif")
  1740. maxsalinityholo2 <- maxsalinityholo/100
  1741. maxtempholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/tempmaxmask2.tif")
  1742. maxtempholo2 <- maxtempholo/100
  1743. rangesalinityholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/salrangemask2.tif")
  1744. rangesalinityholo2 <- rangesalinityholo/100
  1745. rangetempholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/temprangemask2.tif")
  1746. rangetempholo2 <- rangetempholo/100
  1747. Holo.rasters <- raster::stack(maxsalinityholo2, maxtempholo2, rangesalinityholo2, rangetempholo2)
  1748. # optionally assigning a crs if one isn't provided
  1749. crs(Holo.rasters) <- wgs1984
  1750. names(Holo.rasters)
  1751. names(Holo.rasters) <- c('maxsalinity', 'maxtemp', 'rangesalinity', 'rangetemp')
  1752. ### Ecospat Analysis of Niche Equivalency and Similary
  1753. #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1754. # Set working directory for saving plots and test results
  1755. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/ACERV/masked/maskedtwice/Ecospat_acerv_10_2_24")
  1756. combine.lat = c(AcervPres$lat, AcervHolo$lat)
  1757. combine.lon = c(AcervPres$long, AcervHolo$long)
  1758. #I need to turn the points into a spatvector (
  1759. library(terra)
  1760. ptspres <- vect(cbind(AcervPres$long, AcervPres$lat))
  1761. ptsholo <- vect(cbind(AcervHolo$long, AcervHolo$lat))
  1762. # get random sample - background point locations -
  1763. rasterobject <- rast(Prescomp.rasters)
  1764. bgpres = ENMTools::background.buffer(points = ptspres , buffer.width = 200, buffer.type = "circles", mask = rasterobject,
  1765. return.type = "points", n = 500)
  1766. rasterobject <- rast(Holo.rasters)
  1767. bgholo = ENMTools::background.buffer(points = ptsholo , buffer.width = 200, buffer.type = "circles", mask = rasterobject,
  1768. return.type = "points", n = 500)
  1769. # get environmental data from occ points
  1770. extractpres = na.omit(cbind(AcervPres[2:3], raster::extract(Prescomp.rasters, AcervPres[2:3]), rep(1, nrow(AcervPres))))
  1771. extractholo = na.omit(cbind(AcervHolo[2:3], raster::extract(Holo.rasters, AcervHolo[2:3]), rep(1, nrow(AcervHolo))))
  1772. #change name of last column to occ (represents presence = 1)
  1773. colnames(extractpres)[ncol(extractpres)] = 'occ'
  1774. colnames(extractholo)[ncol(extractholo)] = 'occ'
  1775. # get environmental data from bg points
  1776. extbgpres = na.omit(cbind(geom(bgpres)[,3:4], raster::extract(Prescomp.rasters, geom(bgpres)[,3:4]), rep(0, nrow(geom(bgpres)))))
  1777. extbgholo = na.omit(cbind(geom(bgholo)[,3:4], raster::extract(Holo.rasters, geom(bgholo)[,3:4]), rep(0, nrow(geom(bgholo)))))
  1778. # change name of last column to occ (represents absence = 0)
  1779. colnames(extbgpres)[ncol(extbgpres)] = 'occ'
  1780. colnames(extbgholo)[ncol(extbgholo)] = 'occ'
  1781. colnames(extbgpres)[1] = 'long'
  1782. colnames(extbgpres)[2] = 'lat'
  1783. colnames(extbgholo)[1] = 'long'
  1784. colnames(extbgholo)[2] = 'lat'
  1785. # merge data from occ and bg
  1786. datPresAcerv = rbind(extractpres, extbgpres)
  1787. datHoloAcerv = rbind(extractholo, extbgholo)
  1788. #principle component analysis
  1789. pca.env <- dudi.pca(
  1790. rbind(datHoloAcerv, datPresAcerv)[,3:6],
  1791. scannf=FALSE,
  1792. nf=2
  1793. )
  1794. # look at variable contribution
  1795. ecospat.plot.contrib(contrib=pca.env$co, eigen=pca.env$eig)
  1796. # Save pdf of PCA plot
  1797. pdf('ecospat_Acervpresholo.pdf')
  1798. ecospat.plot.contrib(contrib=pca.env$co, eigen=pca.env$eig)
  1799. scores.globclim<-pca.env$li # PCA scores for the whole study area
  1800. scores.globclim<-pca.env$li # PCA scores for the whole study area (all points)
  1801. scores.sppres <- suprow(pca.env,
  1802. extractpres[which(extractpres[, 7]==1),3:6])$li # PCA scores for the first interval occ pts distribution
  1803. scores.spholo <- suprow(pca.env,
  1804. extractholo[which(extractholo[,7]==1),3:6])$li # PCA scores for the second interal occ pts distribution
  1805. scores.climholo <- suprow(pca.env,datHoloAcerv[,3:6])$li # PCA scores for the first interval study area
  1806. scores.climpres <- suprow(pca.env,datPresAcerv[,3:6])$li # PCA scores for the second interval study area
  1807. # density distribtuion for first interval
  1808. grid.Acervholo <- ecospat.grid.clim.dyn(
  1809. glob = scores.globclim,
  1810. glob1 = scores.climholo,
  1811. sp = scores.spholo,
  1812. R = 100,
  1813. th.sp = 0
  1814. )
  1815. # density distribution for second interval
  1816. grid.Acervpres <- ecospat.grid.clim.dyn(
  1817. glob = scores.globclim,
  1818. glob1 = scores.climpres,
  1819. sp = scores.sppres,
  1820. R = 100,
  1821. th.sp = 0
  1822. )
  1823. histpres <- hist(grid.Acervpres$glob1)
  1824. histholo <- hist(grid.Acervholo$glob1)
  1825. plot( histpres, col=rgb(0,0,1,1/4)) # first histogram
  1826. plot( histholo, col=rgb(1,0,0,1/4), add=T)
  1827. # Schoener's D metric and I metric
  1828. D.overlap <- ecospat.niche.overlap (grid.Acervholo, grid.Acervpres, cor=T)
  1829. D.overlap
  1830. write.csv(D.overlap,"presAcerv_holoAcerv_I_D.csv",row.names=FALSE)
  1831. ## Niche Equivalency Test
  1832. ## Obs: observed overlaps, sim: similulated overlaps, p.D: pvalue of the test on D
  1833. ## p.I: pvalue of the test on I
  1834. ## Test for greater or lower equivalency
  1835. eq.testgr <- ecospat.niche.equivalency.test(grid.Acervholo, grid.Acervpres,
  1836. rep=1000, overlap.alternative = "higher",ncores=4) ##rep = 1000 recommended for operational runs
  1837. eq.testlw <- ecospat.niche.equivalency.test(grid.Acervholo, grid.Acervpres,
  1838. rep=1000, overlap.alternative = "lower",ncores=4) ##rep = 1000 recommended for operational runs
  1839. nichdynindex <- ecospat.niche.dyn.index(grid.Acervholo, grid.Acervpres, intersection = NA)
  1840. #ecospat.niche.dyn.index(nativeGrid, invasiveGrid, intersection = 0.1)$dynamic.index.w
  1841. nichdynindex
  1842. # write p values of equivalency test
  1843. p_EQ_DI = cbind("p.D_GR"=eq.testgr$p.D,"p.I_GR"=eq.testgr$p.I,"p.D_LW"=eq.testlw$p.D,"p.I_LW"=eq.testlw$p.D)
  1844. write.csv(p_EQ_DI,"glycim_EQ_TestAcervpresholo.csv",row.names=FALSE)
  1845. p_EQ_DI
  1846. ## Test for greater (niche conservatism) or lower (niche divergence) similarity
  1847. sim.testgr <- ecospat.niche.similarity.test(grid.Acervholo, grid.Acervpres,
  1848. rep=1000, overlap.alternative = "higher",
  1849. rand.type=2,ncores=4)
  1850. sim.testlw <- ecospat.niche.similarity.test(grid.Acervholo, grid.Acervpres,
  1851. rep=1000, overlap.alternative = "lower",
  1852. rand.type=2,ncores=4)
  1853. # write p values of similarity test
  1854. p_SIM_DI = cbind("p.D_GR"=sim.testgr$p.D,"p.I_GR"=sim.testgr$p.I,"p.D_LW"=sim.testlw$p.D,"p.I_LW"=sim.testlw$p.D)
  1855. write.csv(p_SIM_DI,"presholoAcerv_SIM_Test.csv",row.names=FALSE)
  1856. p_SIM_DI
  1857. # Plot test distributions
  1858. ecospat.plot.overlap.test(eq.testgr, "D", "Greater Equivalency")
  1859. ecospat.plot.overlap.test(eq.testlw, "D", "Lower Equivalency")
  1860. ecospat.plot.overlap.test(sim.testgr, "D", "Greater Similarity")
  1861. ecospat.plot.overlap.test(sim.testlw, "D", "Lower Similarity")
  1862. ## Plot niche space for first (grid.climholo) and second (grid.climpres) intervals
  1863. ecospat.plot.niche (grid.Acervpres, title='Acervpres', name.axis1='PC1', name.axis2='PC2', cor=FALSE)
  1864. ecospat.plot.niche (grid.Acervholo, title='Acervholo', name.axis1='PC1', name.axis2='PC2')
  1865. ## Plot niche overlap
  1866. ecospat.plot.niche.dyn(z1 = grid.Acervholo, z2 = grid.Acervpres, quant=0.25, interest=2,
  1867. title= "A. cerv Holo to Pres", name.axis1="PC1",
  1868. name.axis2="PC2", col.unf = "#313695", col.exp = "#abd9d9", col.stab = '#74add1', colZ1 =
  1869. "#313695", colZ2 = "#abd9d9", transparency = 40)
  1870. ecospat.shift.centroids(sp1 = scores.spholo, sp2 = scores.sppres, scores.climholo, scores.climpres, col = 'white')
  1871. rstudioapi::savePlotAsImage("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/ACERV/masked/maskedtwice/Ecospat_acerv_10_2_24/figures/A. cerv Holo to Pres.png",width=1000,height=750)
  1872. # Save pdf of plots
  1873. ### Look at niche expantion, stability, and unfilling
  1874. # NA=analysis on entire area, 0=analysis on only overlapping, 0.05=analysis on 5th quantile intersection
  1875. dynam_allAreas = ecospat.niche.dyn.index (z1 = grid.Acervholo, z2 = grid.Acervpres, intersection=NA)
  1876. dynam_overlap = ecospat.niche.dyn.index (z1 = grid.Acervholo, z2 = grid.Acervpres, intersection=0)
  1877. # write csv of niche dynmaic percentages
  1878. Niche_Ex_St = cbind("AllAreas"=dynam_allAreas$dynamic.index.w,
  1879. "Overlapping"=dynam_overlap$dynamic.index.w)
  1880. Niche_Ex_St
  1881. write.csv(Niche_Ex_St,"GlycymDynamicsAcervholopres.csv",row.names=TRUE)
  1882. ############################################ APAL ECOSPAT ###################
  1883. ## Read in shapefiles of cleaned occ data ##
  1884. ########################occurrence data######################
  1885. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/Master_files_apal_add_mask")
  1886. ApalPres = read.csv("masterpres.occs.csv")
  1887. ApalPres = as(ApalPres,'data.frame')
  1888. ApalHolo = read.csv("masterholo.occs.csv")
  1889. ApalHolo = as(ApalHolo,'data.frame')
  1890. #convert to dataframe for use in ecospat
  1891. ###################environmental###################
  1892. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present")
  1893. # Upload basic rasters for First interval (Present)
  1894. Prescomp.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present", pattern='\\.tif$')
  1895. Prescomp.files
  1896. maxsalinitypres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/maxsalinity.tif")
  1897. maxsalinitypres
  1898. maxtemppres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/maxtemp.tif")
  1899. maxtemppres
  1900. rangesalinitypres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/rangesalinity.tif")
  1901. rangesalinitypres
  1902. rangetemppres <- raster ("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/rangetemp.tif")
  1903. rangetemppres
  1904. # make sure order of how e-layers are read in is the same for each analysis extent (i.e., time bins or spatial areas)
  1905. Prescomp.rasters <- raster::stack(c(maxsalinitypres, maxtemppres, rangesalinitypres, rangetemppres))
  1906. wgs1984 <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
  1907. # optionally assigning a crs if one isn't provided
  1908. crs(Prescomp.rasters) <- wgs1984
  1909. names(Prescomp.rasters)
  1910. names(Prescomp.rasters) <- c('maxsalinity', 'maxtemp', 'rangesalinity', 'rangetemp')
  1911. #Upload basic rasters for Second interval (Holocene)
  1912. ## holocene+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1913. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam")
  1914. Holo.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam", pattern='\\.tif$')
  1915. #Holo.files
  1916. # scaling holocene layers
  1917. maxsalinityholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/salmaxmask2.tif")
  1918. maxsalinityholo2 <- maxsalinityholo/100
  1919. maxtempholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/tempmaxmask2.tif")
  1920. maxtempholo2 <- maxtempholo/100
  1921. rangesalinityholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/salrangemask2.tif")
  1922. rangesalinityholo2 <- rangesalinityholo/100
  1923. rangetempholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/temprangemask2.tif")
  1924. rangetempholo2 <- rangetempholo/100
  1925. Holo.rasters <- raster::stack(maxsalinityholo2, maxtempholo2, rangesalinityholo2, rangetempholo2)
  1926. # optionally assigning a crs if one isn't provided
  1927. crs(Holo.rasters) <- wgs1984
  1928. names(Holo.rasters)
  1929. names(Holo.rasters) <- c('maxsalinity', 'maxtemp', 'rangesalinity', 'rangetemp')
  1930. ### Ecospat Analysis of Niche Equivalency and Similary
  1931. #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1932. # Set working directory for saving plots and test results
  1933. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/maskedtwice/Ecospat_apal_10_2_24")
  1934. combine.lat = c(ApalPres$lat, ApalHolo$lat) #, ApalLGM$lat)
  1935. combine.lon = c(ApalPres$long, ApalHolo$long) #, ApalLGM$long)
  1936. #I need to turn the points into a spatvector (
  1937. ptspres <- vect(cbind(ApalPres$long, ApalPres$lat))
  1938. ptsholo <- vect(cbind(ApalHolo$long, ApalHolo$lat))
  1939. # get random sample - background point locations -
  1940. rasterobject <- rast(Prescomp.rasters)
  1941. bgpres = ENMTools::background.buffer(points = ptspres , buffer.width = 200, buffer.type = "circles", mask = rasterobject,
  1942. return.type = "points", n = 500)
  1943. rasterobject <- rast(Holo.rasters)
  1944. bgholo = ENMTools::background.buffer(points = ptsholo , buffer.width = 200, buffer.type = "circles", mask = rasterobject,
  1945. return.type = "points", n = 500)
  1946. # get environmental data from occ points
  1947. extractpres = na.omit(cbind(ApalPres[2:3], raster::extract(Prescomp.rasters, ApalPres[2:3]), rep(1, nrow(ApalPres))))
  1948. extractholo = na.omit(cbind(ApalHolo[2:3], raster::extract(Holo.rasters, ApalHolo[2:3]), rep(1, nrow(ApalHolo))))
  1949. #change name of last column to occ (represents presence = 1)
  1950. colnames(extractpres)[ncol(extractpres)] = 'occ'
  1951. colnames(extractholo)[ncol(extractholo)] = 'occ'
  1952. # get environmental data from bg points
  1953. #cant do stack-- need to do all???
  1954. extbgpres = na.omit(cbind(geom(bgpres)[,3:4], raster::extract(Prescomp.rasters, geom(bgpres)[,3:4]), rep(0, nrow(geom(bgpres)))))
  1955. extbgholo = na.omit(cbind(geom(bgholo)[,3:4], raster::extract(Holo.rasters, geom(bgholo)[,3:4]), rep(0, nrow(geom(bgholo)))))
  1956. # change name of last column to occ (represents absence = 0)
  1957. colnames(extbgpres)[ncol(extbgpres)] = 'occ'
  1958. colnames(extbgholo)[ncol(extbgholo)] = 'occ'
  1959. colnames(extbgpres)[1] = 'long'
  1960. colnames(extbgpres)[2] = 'lat'
  1961. colnames(extbgholo)[1] = 'long'
  1962. colnames(extbgholo)[2] = 'lat'
  1963. # merge data from occ and bg
  1964. datPresApal = rbind(extractpres, extbgpres)
  1965. datHoloApal = rbind(extractholo, extbgholo)
  1966. #principle component analysis
  1967. pca.env <- dudi.pca(
  1968. rbind(datHoloApal, datPresApal)[,3:6],
  1969. scannf=FALSE,
  1970. nf=2
  1971. )
  1972. # look at variable contribution
  1973. ecospat.plot.contrib(contrib=pca.env$co, eigen=pca.env$eig)
  1974. # Save pdf of PCA plot
  1975. pdf('ecospat_Apalpresholo.pdf')
  1976. ecospat.plot.contrib(contrib=pca.env$co, eigen=pca.env$eig)
  1977. scores.globclim<-pca.env$li # PCA scores for the whole study area
  1978. scores.globclim<-pca.env$li # PCA scores for the whole study area (all points)
  1979. scores.sppres <- suprow(pca.env,
  1980. extractpres[which(extractpres[, 7]==1),3:6])$li # PCA scores for the first interval occ pts distribution
  1981. scores.spholo <- suprow(pca.env,
  1982. extractholo[which(extractholo[,7]==1),3:6])$li # PCA scores for the second interal occ pts distribution
  1983. scores.climholo <- suprow(pca.env,datHoloApal[,3:6])$li # PCA scores for the first interval study area
  1984. scores.climpres <- suprow(pca.env,datPresApal[,3:6])$li # PCA scores for the second interval study area
  1985. # density distribtuion for first interval
  1986. grid.Apalholo <- ecospat.grid.clim.dyn(
  1987. glob = scores.globclim,
  1988. glob1 = scores.climholo,
  1989. sp = scores.spholo,
  1990. R = 100,
  1991. th.sp = 0
  1992. )
  1993. # density distribution for second interval
  1994. grid.Apalpres <- ecospat.grid.clim.dyn(
  1995. glob = scores.globclim,
  1996. glob1 = scores.climpres,
  1997. sp = scores.sppres,
  1998. R = 100,
  1999. th.sp = 0
  2000. )
  2001. histpres <- hist(grid.Apalpres$glob1)
  2002. histholo <- hist(grid.Apalholo$glob1)
  2003. plot( histpres, col=rgb(0,0,1,1/4)) # first histogram
  2004. plot( histholo, col=rgb(1,0,0,1/4), add=T)
  2005. # Schoener's D metric and I metric
  2006. D.overlap <- ecospat.niche.overlap (grid.Apalholo, grid.Apalpres, cor=T)
  2007. D.overlap
  2008. write.csv(D.overlap,"presApal_holoApal_I_D.csv",row.names=FALSE)
  2009. ## Niche Equivalency Test
  2010. ## Obs: observed overlaps, sim: similulated overlaps, p.D: pvalue of the test on D
  2011. ## p.I: pvalue of the test on I
  2012. ## Test for greater or lower equivalency
  2013. eq.testgr <- ecospat.niche.equivalency.test(grid.Apalholo, grid.Apalpres,
  2014. rep=1000, overlap.alternative = "higher",ncores=4) ##rep = 1000 recommended for operational runs
  2015. eq.testlw <- ecospat.niche.equivalency.test(grid.Apalholo, grid.Apalpres,
  2016. rep=1000, overlap.alternative = "lower",ncores=4) ##rep = 1000 recommended for operational runs
  2017. nichdynindex <- ecospat.niche.dyn.index(grid.Apalholo, grid.Apalpres, intersection = NA)
  2018. #ecospat.niche.dyn.index(nativeGrid, invasiveGrid, intersection = 0.1)$dynamic.index.w
  2019. nichdynindex
  2020. # write p values of equivalency test
  2021. p_EQ_DI = cbind("p.D_GR"=eq.testgr$p.D,"p.I_GR"=eq.testgr$p.I,"p.D_LW"=eq.testlw$p.D,"p.I_LW"=eq.testlw$p.D)
  2022. write.csv(p_EQ_DI,"glycim_EQ_TestApalpresholo.csv",row.names=FALSE)
  2023. p_EQ_DI
  2024. ## Test for greater (niche conservatism) or lower (niche divergence) similarity
  2025. sim.testgr <- ecospat.niche.similarity.test(grid.Apalholo, grid.Apalpres,
  2026. rep=1000, overlap.alternative = "higher",
  2027. rand.type=2,ncores=4)
  2028. sim.testlw <- ecospat.niche.similarity.test(grid.Apalholo, grid.Apalpres,
  2029. rep=1000, overlap.alternative = "lower",
  2030. rand.type=2,ncores=4)
  2031. # write p values of similarity test
  2032. p_SIM_DI = cbind("p.D_GR"=sim.testgr$p.D,"p.I_GR"=sim.testgr$p.I,"p.D_LW"=sim.testlw$p.D,"p.I_LW"=sim.testlw$p.D)
  2033. write.csv(p_SIM_DI,"presholoApal_SIM_Test.csv",row.names=FALSE)
  2034. p_SIM_DI
  2035. #p.D_GR p.I_GR p.D_LW p.I_LW
  2036. #[1,] 0.04595405 0.03996004 0.9480519 0.9480519
  2037. #dev.off()
  2038. # Plot test distributions
  2039. ecospat.plot.overlap.test(eq.testgr, "D", "Greater Equivalency")
  2040. ecospat.plot.overlap.test(eq.testlw, "D", "Lower Equivalency")
  2041. ecospat.plot.overlap.test(sim.testgr, "D", "Greater Similarity")
  2042. ecospat.plot.overlap.test(sim.testlw, "D", "Lower Similarity")
  2043. ## Plot niche space for first (grid.climholo) and second (grid.climpres) intervals
  2044. ecospat.plot.niche (grid.Apalpres, title='Apalpres', name.axis1='PC1', name.axis2='PC2', cor=FALSE)
  2045. ecospat.plot.niche (grid.Apalholo, title='Apalholo', name.axis1='PC1', name.axis2='PC2')
  2046. ## Plot niche overlap
  2047. ecospat.plot.niche.dyn(z1 = grid.Apalholo, z2 = grid.Apalpres, quant=0.25, interest=2,
  2048. title= "A. pal Holo to Pres", name.axis1="PC1",
  2049. name.axis2="PC2", col.unf = "#313695", col.exp = "#abd9d9", col.stab = 'black', colZ1 =
  2050. "#313695", colZ2 = "#abd9d9", transparency = 40)
  2051. ecospat.shift.centroids(sp1 = scores.spholo, sp2 = scores.sppres, scores.climholo, scores.climpres, col = 'white')
  2052. rstudioapi::savePlotAsImage("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/maskedtwice/Ecospat_apal_10_2_24/figures/A. pal Holo to Pres.png",width=1000,height=750)
  2053. #___________________________
  2054. # Save pdf of plots
  2055. ### Look at niche expantion, stability, and unfilling
  2056. # NA=analysis on entire area, 0=analysis on only overlapping, 0.05=analysis on 5th quantile intersection
  2057. dynam_allAreas = ecospat.niche.dyn.index (z1 = grid.Apalholo, z2 = grid.Apalpres, intersection=NA)
  2058. dynam_overlap = ecospat.niche.dyn.index (z1 = grid.Apalholo, z2 = grid.Apalpres, intersection=0)
  2059. # write csv of niche dynmaic percentages
  2060. Niche_Ex_St = cbind("AllAreas"=dynam_allAreas$dynamic.index.w,
  2061. "Overlapping"=dynam_overlap$dynamic.index.w)
  2062. Niche_Ex_St
  2063. write.csv(Niche_Ex_St,"GlycymDynamicsApalholopres.csv",row.names=TRUE)
  2064. ########################## CNAT ECOSPAT #############
  2065. #need cleaned occurrence data and environmental data rasters
  2066. ## Read in shapefiles of cleaned occ data ##
  2067. ########################occurrence data######################
  2068. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/CNAT/masked/Master_files_cnat_add_mask")
  2069. CnatPres = read.csv("masterpres.occs.csv")
  2070. CnatPres = as(CnatPres,'data.frame')
  2071. CnatHolo = read.csv("masterholo.occs.csv")
  2072. CnatHolo = as(CnatHolo,'data.frame')
  2073. #convert to dataframe for use in ecospat
  2074. ##################environmental###################
  2075. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present")
  2076. # Upload basic rasters for First interval (Present)
  2077. Prescomp.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present", pattern='\\.tif$')
  2078. Prescomp.files
  2079. maxsalinitypres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/maxsalinity.tif")
  2080. maxsalinitypres
  2081. maxtemppres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/maxtemp.tif")
  2082. maxtemppres
  2083. rangesalinitypres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/rangesalinity.tif")
  2084. rangesalinitypres
  2085. rangetemppres <- raster ("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/rangetemp.tif")
  2086. rangetemppres
  2087. # make sure order of how e-layers are read in is the same for each analysis extent (i.e., time bins or spatial areas)
  2088. Prescomp.rasters <- raster::stack(c(maxsalinitypres, maxtemppres, rangesalinitypres, rangetemppres))
  2089. wgs1984 <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
  2090. # optionally assigning a crs if one isn't provided
  2091. crs(Prescomp.rasters) <- wgs1984
  2092. names(Prescomp.rasters)
  2093. names(Prescomp.rasters) <- c('maxsalinity', 'maxtemp', 'rangesalinity', 'rangetemp')
  2094. #Upload basic rasters for Second interval (Holocene)
  2095. ## holocene+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2096. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam")
  2097. Holo.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam", pattern='\\.tif$')
  2098. #Holo.files
  2099. maxsalinityholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/salmaxmask2.tif")
  2100. maxsalinityholo2 <- maxsalinityholo/100
  2101. maxtempholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/tempmaxmask2.tif")
  2102. maxtempholo2 <- maxtempholo/100
  2103. rangesalinityholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/salrangemask2.tif")
  2104. rangesalinityholo2 <- rangesalinityholo/100
  2105. rangetempholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/temprangemask2.tif")
  2106. rangetempholo2 <- rangetempholo/100
  2107. Holo.rasters <- raster::stack(maxsalinityholo2, maxtempholo2, rangesalinityholo2, rangetempholo2)
  2108. # optionally assigning a crs if one isn't provided
  2109. crs(Holo.rasters) <- wgs1984
  2110. names(Holo.rasters)
  2111. names(Holo.rasters) <- c('maxsalinity', 'maxtemp', 'rangesalinity', 'rangetemp')
  2112. ### Ecospat Analysis of Niche Equivalency and Similary
  2113. #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2114. # Set working directory for saving plots and test results
  2115. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/CNAT/masked/maskedtwice/Ecospat_cnat_10_2_24")
  2116. combine.lat = c(CnatPres$lat, CnatHolo$lat) #, CnatLGM$lat)
  2117. combine.lon = c(CnatPres$long, CnatHolo$long) #, CnatLGM$long)
  2118. #combine.lat = c(glyMaa$coords.x1, glyDan$coords.x1)
  2119. #combine.lon = c(glyMaa$coords.x2, glyDan$coords.x2)
  2120. #extt=extent(c(min(combine.lon)-5, max(combine.lon)+5, min(combine.lat)-5, max(combine.lat)+5)) # useful if mapping pts and env
  2121. #I need to turn the points into a spatvector (
  2122. library(terra)
  2123. ptspres <- vect(cbind(CnatPres$long, CnatPres$lat))
  2124. ptsholo <- vect(cbind(CnatHolo$long, CnatHolo$lat))
  2125. # get random sample - background point locations -
  2126. rasterobject <- rast(Prescomp.rasters)
  2127. bgpres = ENMTools::background.buffer(points = ptspres , buffer.width = 200, buffer.type = "circles", mask = rasterobject,
  2128. return.type = "points", n = 500)
  2129. rasterobject <- rast(Holo.rasters)
  2130. bgholo = ENMTools::background.buffer(points = ptsholo , buffer.width = 200, buffer.type = "circles", mask = rasterobject,
  2131. return.type = "points", n = 500)
  2132. # get environmental data from occ points
  2133. extractpres = na.omit(cbind(CnatPres[2:3], raster::extract(Prescomp.rasters, CnatPres[2:3]), rep(1, nrow(CnatPres))))
  2134. extractholo = na.omit(cbind(CnatHolo[2:3], raster::extract(Holo.rasters, CnatHolo[2:3]), rep(1, nrow(CnatHolo))))
  2135. #change name of last column to occ (represents presence = 1)
  2136. colnames(extractpres)[ncol(extractpres)] = 'occ'
  2137. colnames(extractholo)[ncol(extractholo)] = 'occ'
  2138. # get environmental data from bg points
  2139. #cant do stack-- need to do all???
  2140. extbgpres = na.omit(cbind(geom(bgpres)[,3:4], raster::extract(Prescomp.rasters, geom(bgpres)[,3:4]), rep(0, nrow(geom(bgpres)))))
  2141. extbgholo = na.omit(cbind(geom(bgholo)[,3:4], raster::extract(Holo.rasters, geom(bgholo)[,3:4]), rep(0, nrow(geom(bgholo)))))
  2142. # change name of last column to occ (represents absence = 0)
  2143. colnames(extbgpres)[ncol(extbgpres)] = 'occ'
  2144. colnames(extbgholo)[ncol(extbgholo)] = 'occ'
  2145. colnames(extbgpres)[1] = 'long'
  2146. colnames(extbgpres)[2] = 'lat'
  2147. colnames(extbgholo)[1] = 'long'
  2148. colnames(extbgholo)[2] = 'lat'
  2149. #colnames(extbgholo)[ncol(extbgholo)] = 'occ'
  2150. # merge data from occ and bg
  2151. datPresCnat = rbind(extractpres, extbgpres)
  2152. datHoloCnat = rbind(extractholo, extbgholo)
  2153. #principle component analysis
  2154. pca.env <- dudi.pca(
  2155. rbind(datHoloCnat, datPresCnat)[,3:6],
  2156. scannf=FALSE,
  2157. nf=2
  2158. )
  2159. # look at variable contribution
  2160. ecospat.plot.contrib(contrib=pca.env$co, eigen=pca.env$eig)
  2161. #dev.off()
  2162. # Save pdf of PCA plot
  2163. pdf('ecospat_Cnatpresholo.pdf')
  2164. ecospat.plot.contrib(contrib=pca.env$co, eigen=pca.env$eig)
  2165. scores.globclim<-pca.env$li # PCA scores for the whole study area
  2166. scores.globclim<-pca.env$li # PCA scores for the whole study area (all points)
  2167. scores.sppres <- suprow(pca.env,
  2168. extractpres[which(extractpres[, 7]==1),3:6])$li # PCA scores for the first interval occ pts distribution
  2169. scores.spholo <- suprow(pca.env,
  2170. extractholo[which(extractholo[,7]==1),3:6])$li # PCA scores for the second interal occ pts distribution
  2171. scores.climholo <- suprow(pca.env,datHoloCnat[,3:6])$li # PCA scores for the first interval study area
  2172. scores.climpres <- suprow(pca.env,datPresCnat[,3:6])$li # PCA scores for the second interval study area
  2173. #dev.on()
  2174. # density distribtuion for first interval
  2175. grid.Cnatholo <- ecospat.grid.clim.dyn(
  2176. glob = scores.globclim,
  2177. glob1 = scores.climholo,
  2178. sp = scores.spholo,
  2179. R = 100,
  2180. th.sp = 0
  2181. )
  2182. # density distribution for second interval
  2183. grid.Cnatpres <- ecospat.grid.clim.dyn(
  2184. glob = scores.globclim,
  2185. glob1 = scores.climpres,
  2186. sp = scores.sppres,
  2187. R = 100,
  2188. th.sp = 0
  2189. )
  2190. #dev.off()
  2191. histpres <- hist(grid.Cnatpres$glob1)
  2192. histholo <- hist(grid.Cnatholo$glob1)
  2193. plot( histpres, col=rgb(0,0,1,1/4)) # first histogram
  2194. plot( histholo, col=rgb(1,0,0,1/4), add=T)
  2195. # Schoener's D metric and I metric
  2196. D.overlap <- ecospat.niche.overlap (grid.Cnatholo, grid.Cnatpres, cor=T)
  2197. D.overlap
  2198. write.csv(D.overlap,"presCnat_holoCnat_I_D.csv",row.names=FALSE)
  2199. ## Niche Equivalency Test
  2200. ## Obs: observed overlaps, sim: similulated overlaps, p.D: pvalue of the test on D
  2201. ## p.I: pvalue of the test on I
  2202. ## Test for greater or lower equivalency
  2203. eq.testgr <- ecospat.niche.equivalency.test(grid.Cnatholo, grid.Cnatpres,
  2204. rep=1000, overlap.alternative = "higher",ncores=4) ##rep = 1000 recommended for operational runs
  2205. eq.testlw <- ecospat.niche.equivalency.test(grid.Cnatholo, grid.Cnatpres,
  2206. rep=1000, overlap.alternative = "lower",ncores=4) ##rep = 1000 recommended for operational runs
  2207. nichdynindex <- ecospat.niche.dyn.index(grid.Cnatholo, grid.Cnatpres, intersection = NA)
  2208. #ecospat.niche.dyn.index(nativeGrid, invasiveGrid, intersection = 0.1)$dynamic.index.w
  2209. nichdynindex
  2210. # write p values of equivalency test
  2211. p_EQ_DI = cbind("p.D_GR"=eq.testgr$p.D,"p.I_GR"=eq.testgr$p.I,"p.D_LW"=eq.testlw$p.D,"p.I_LW"=eq.testlw$p.D)
  2212. write.csv(p_EQ_DI,"glycim_EQ_TestCnatpresholo.csv",row.names=FALSE)
  2213. p_EQ_DI
  2214. ## Test for greater (niche conservatism) or lower (niche divergence) similarity
  2215. sim.testgr <- ecospat.niche.similarity.test(grid.Cnatholo, grid.Cnatpres,
  2216. rep=1000, overlap.alternative = "higher",
  2217. rand.type=2,ncores=4)
  2218. sim.testlw <- ecospat.niche.similarity.test(grid.Cnatholo, grid.Cnatpres,
  2219. rep=1000, overlap.alternative = "lower",
  2220. rand.type=2,ncores=4)
  2221. # write p values of similarity test
  2222. p_SIM_DI = cbind("p.D_GR"=sim.testgr$p.D,"p.I_GR"=sim.testgr$p.I,"p.D_LW"=sim.testlw$p.D,"p.I_LW"=sim.testlw$p.D)
  2223. write.csv(p_SIM_DI,"presholoCnat_SIM_Test.csv",row.names=FALSE)
  2224. p_SIM_DI
  2225. #p.D_GR p.I_GR p.D_LW p.I_LW
  2226. #[1,] 0.04595405 0.03996004 0.9480519 0.9480519
  2227. #dev.off()
  2228. # Plot test distributions
  2229. ecospat.plot.overlap.test(eq.testgr, "D", "Greater Equivalency")
  2230. ecospat.plot.overlap.test(eq.testlw, "D", "Lower Equivalency")
  2231. ecospat.plot.overlap.test(sim.testgr, "D", "Greater Similarity")
  2232. ecospat.plot.overlap.test(sim.testlw, "D", "Lower Similarity")
  2233. ## Plot niche space for first (grid.climholo) and second (grid.climpres) intervals
  2234. ecospat.plot.niche (grid.Cnatpres, title='Cnatpres', name.axis1='PC1', name.axis2='PC2', cor=FALSE)
  2235. ecospat.plot.niche (grid.Cnatholo, title='Cnatholo', name.axis1='PC1', name.axis2='PC2')
  2236. ## Plot niche overlap
  2237. ecospat.plot.niche.dyn(z1 = grid.Cnatholo, z2 = grid.Cnatpres, quant=0.25, interest=2,
  2238. title= "C. nat Holo to Pres", name.axis1="PC1",
  2239. name.axis2="PC2", col.unf = "#313695", col.exp = "#abd9d9", col.stab = 'black', colZ1 =
  2240. "#313695", colZ2 = "#abd9d9", transparency = 40)
  2241. ecospat.shift.centroids(sp1 = scores.spholo, sp2 = scores.sppres, scores.climholo, scores.climpres, col = 'white')
  2242. rstudioapi::savePlotAsImage("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/CNAT/masked/maskedtwice/Ecospat_cnat_10_2_24/figures/C. nat Holo to Pres.pdf",width=1000,height=750)
  2243. #___________________________
  2244. ### Look at niche expantion, stability, and unfilling
  2245. # NA=analysis on entire area, 0=analysis on only overlapping, 0.05=analysis on 5th quantile intersection
  2246. dynam_allAreas = ecospat.niche.dyn.index (z1 = grid.Cnatholo, z2 = grid.Cnatpres, intersection=NA)
  2247. dynam_overlap = ecospat.niche.dyn.index (z1 = grid.Cnatholo, z2 = grid.Cnatpres, intersection=0)
  2248. # write csv of niche dynmaic percentages
  2249. Niche_Ex_St = cbind("AllAreas"=dynam_allAreas$dynamic.index.w,
  2250. "Overlapping"=dynam_overlap$dynamic.index.w)
  2251. Niche_Ex_St
  2252. write.csv(Niche_Ex_St,"GlycymDynamicsCnatholopres.csv",row.names=TRUE)
  2253. ############################ PAST ECOSPAT ######################
  2254. #### MODEL COMPARISON ####
  2255. #need cleaned occurrence data and environmental data rasters
  2256. ## Read in shapefiles of cleaned occ data ##
  2257. ########################occurrence data######################
  2258. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/PAST/masked/Master_files_past_add_mask")
  2259. PastPres = read.csv("masterpres.occs.csv")
  2260. PastPres = as(PastPres,'data.frame')
  2261. PastHolo = read.csv("masterholo.occs.csv")
  2262. PastHolo = as(PastHolo,'data.frame')
  2263. #convert to dataframe for use in ecospat
  2264. ###################environmental###################
  2265. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present")
  2266. # Upload basic rasters for First interval (Present)
  2267. Prescomp.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present", pattern='\\.tif$')
  2268. Prescomp.files
  2269. maxsalinitypres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/maxsalinity.tif")
  2270. maxsalinitypres
  2271. maxtemppres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/maxtemp.tif")
  2272. maxtemppres
  2273. rangesalinitypres <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/rangesalinity.tif")
  2274. rangesalinitypres
  2275. rangetemppres <- raster ("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/BIO-Oracle Future/MASKED/present/rangetemp.tif")
  2276. rangetemppres
  2277. # make sure order of how e-layers are read in is the same for each analysis extent (i.e., time bins or spatial areas)
  2278. Prescomp.rasters <- raster::stack(c(maxsalinitypres, maxtemppres, rangesalinitypres, rangetemppres))
  2279. wgs1984 <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
  2280. # optionally assigning a crs if one isn't provided
  2281. crs(Prescomp.rasters) <- wgs1984
  2282. names(Prescomp.rasters)
  2283. names(Prescomp.rasters) <- c('maxsalinity', 'maxtemp', 'rangesalinity', 'rangetemp')
  2284. #Upload basic rasters for Second interval (Holocene)
  2285. ## holocene+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2286. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam")
  2287. Holo.files <- list.files(path="/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam", pattern='\\.tif$')
  2288. #Holo.files
  2289. maxsalinityholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/salmaxmask2.tif")
  2290. maxsalinityholo2 <- maxsalinityholo/100
  2291. maxtempholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/tempmaxmask2.tif")
  2292. maxtempholo2 <- maxtempholo/100
  2293. rangesalinityholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/salrangemask2.tif")
  2294. rangesalinityholo2 <- rangesalinityholo/100
  2295. rangetempholo <- raster("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/marspec_env/holomaskcubadrjam/temprangemask2.tif")
  2296. rangetempholo2 <- rangetempholo/100
  2297. Holo.rasters <- raster::stack(maxsalinityholo2, maxtempholo2, rangesalinityholo2, rangetempholo2)
  2298. # optionally assigning a crs if one isn't provided
  2299. crs(Holo.rasters) <- wgs1984
  2300. names(Holo.rasters)
  2301. names(Holo.rasters) <- c('maxsalinity', 'maxtemp', 'rangesalinity', 'rangetemp')
  2302. ### Ecospat Analysis of Niche Equivalency and Similary
  2303. #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2304. # Set working directory for saving plots and test results
  2305. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/PAST/masked/maskedtwice/Ecospat_past_10_2_24")
  2306. combine.lat = c(PastPres$lat, PastHolo$lat) #, PastLGM$lat)
  2307. combine.lon = c(PastPres$long, PastHolo$long) #, PastLGM$long)
  2308. #I need to turn the points into a spatvector (
  2309. ptspres <- vect(cbind(PastPres$long, PastPres$lat))
  2310. ptsholo <- vect(cbind(PastHolo$long, PastHolo$lat))
  2311. # get random sample - background point locations -
  2312. rasterobject <- rast(Prescomp.rasters)
  2313. bgpres = ENMTools::background.buffer(points = ptspres , buffer.width = 200, buffer.type = "circles", mask = rasterobject,
  2314. return.type = "points", n = 500)
  2315. rasterobject <- rast(Holo.rasters)
  2316. bgholo = ENMTools::background.buffer(points = ptsholo , buffer.width = 200, buffer.type = "circles", mask = rasterobject,
  2317. return.type = "points", n = 500)
  2318. # get environmental data from occ points
  2319. extractpres = na.omit(cbind(PastPres[2:3], raster::extract(Prescomp.rasters, PastPres[2:3]), rep(1, nrow(PastPres))))
  2320. extractholo = na.omit(cbind(PastHolo[2:3], raster::extract(Holo.rasters, PastHolo[2:3]), rep(1, nrow(PastHolo))))
  2321. #change name of last column to occ (represents presence = 1)
  2322. colnames(extractpres)[ncol(extractpres)] = 'occ'
  2323. colnames(extractholo)[ncol(extractholo)] = 'occ'
  2324. # get environmental data from bg points
  2325. #cant do stack-- need to do all???
  2326. extbgpres = na.omit(cbind(geom(bgpres)[,3:4], raster::extract(Prescomp.rasters, geom(bgpres)[,3:4]), rep(0, nrow(geom(bgpres)))))
  2327. extbgholo = na.omit(cbind(geom(bgholo)[,3:4], raster::extract(Holo.rasters, geom(bgholo)[,3:4]), rep(0, nrow(geom(bgholo)))))
  2328. # change name of last column to occ (represents absence = 0)
  2329. colnames(extbgpres)[ncol(extbgpres)] = 'occ'
  2330. colnames(extbgholo)[ncol(extbgholo)] = 'occ'
  2331. colnames(extbgpres)[1] = 'long'
  2332. colnames(extbgpres)[2] = 'lat'
  2333. colnames(extbgholo)[1] = 'long'
  2334. colnames(extbgholo)[2] = 'lat'
  2335. #colnames(extbgholo)[ncol(extbgholo)] = 'occ'
  2336. # merge data from occ and bg
  2337. datPresPast = rbind(extractpres, extbgpres)
  2338. datHoloPast = rbind(extractholo, extbgholo)
  2339. #principle component analysis
  2340. pca.env <- dudi.pca(
  2341. rbind(datHoloPast, datPresPast)[,3:6],
  2342. scannf=FALSE,
  2343. nf=2
  2344. )
  2345. # look at variable contribution
  2346. ecospat.plot.contrib(contrib=pca.env$co, eigen=pca.env$eig)
  2347. #dev.off()
  2348. # Save pdf of PCA plot
  2349. pdf('ecospat_Pastpresholo.pdf')
  2350. ecospat.plot.contrib(contrib=pca.env$co, eigen=pca.env$eig)
  2351. scores.globclim<-pca.env$li # PCA scores for the whole study area
  2352. scores.globclim<-pca.env$li # PCA scores for the whole study area (all points)
  2353. scores.sppres <- suprow(pca.env,
  2354. extractpres[which(extractpres[, 7]==1),3:6])$li # PCA scores for the first interval occ pts distribution
  2355. scores.spholo <- suprow(pca.env,
  2356. extractholo[which(extractholo[,7]==1),3:6])$li # PCA scores for the second interal occ pts distribution
  2357. scores.climholo <- suprow(pca.env,datHoloPast[,3:6])$li # PCA scores for the first interval study area
  2358. scores.climpres <- suprow(pca.env,datPresPast[,3:6])$li # PCA scores for the second interval study area
  2359. #dev.on()
  2360. # density distribtuion for first interval
  2361. grid.Pastholo <- ecospat.grid.clim.dyn(
  2362. glob = scores.globclim,
  2363. glob1 = scores.climholo,
  2364. sp = scores.spholo,
  2365. R = 100,
  2366. th.sp = 0
  2367. )
  2368. # density distribution for second interval
  2369. grid.Pastpres <- ecospat.grid.clim.dyn(
  2370. glob = scores.globclim,
  2371. glob1 = scores.climpres,
  2372. sp = scores.sppres,
  2373. R = 100,
  2374. th.sp = 0
  2375. )
  2376. histpres <- hist(grid.Pastpres$glob1)
  2377. histholo <- hist(grid.Pastholo$glob1)
  2378. plot( histpres, col=rgb(0,0,1,1/4)) # first histogram
  2379. plot( histholo, col=rgb(1,0,0,1/4), add=T)
  2380. # Schoener's D metric and I metric
  2381. D.overlap <- ecospat.niche.overlap (grid.Pastholo, grid.Pastpres, cor=T)
  2382. D.overlap
  2383. write.csv(D.overlap,"presPast_holoPast_I_D.csv",row.names=FALSE)
  2384. ## Niche Equivalency Test
  2385. ## Obs: observed overlaps, sim: similulated overlaps, p.D: pvalue of the test on D
  2386. ## p.I: pvalue of the test on I
  2387. ## Test for greater or lower equivalency
  2388. eq.testgr <- ecospat.niche.equivalency.test(grid.Pastholo, grid.Pastpres,
  2389. rep=1000, overlap.alternative = "higher",ncores=4) ##rep = 1000 recommended for operational runs
  2390. eq.testlw <- ecospat.niche.equivalency.test(grid.Pastholo, grid.Pastpres,
  2391. rep=1000, overlap.alternative = "lower",ncores=4) ##rep = 1000 recommended for operational runs
  2392. #this is if they are the same niche I think
  2393. nichdynindex <- ecospat.niche.dyn.index(grid.Pastholo, grid.Pastpres, intersection = NA)
  2394. #ecospat.niche.dyn.index(nativeGrid, invasiveGrid, intersection = 0.1)$dynamic.index.w
  2395. nichdynindex
  2396. # write p values of equivalency test
  2397. p_EQ_DI = cbind("p.D_GR"=eq.testgr$p.D,"p.I_GR"=eq.testgr$p.I,"p.D_LW"=eq.testlw$p.D,"p.I_LW"=eq.testlw$p.D)
  2398. write.csv(p_EQ_DI,"glycim_EQ_TestPastpresholo.csv",row.names=FALSE)
  2399. p_EQ_DI
  2400. ## Test for greater (niche conservatism) or lower (niche divergence) similarity
  2401. sim.testgr <- ecospat.niche.similarity.test(grid.Pastholo, grid.Pastpres,
  2402. rep=1000, overlap.alternative = "higher",
  2403. rand.type=2,ncores=4)
  2404. sim.testlw <- ecospat.niche.similarity.test(grid.Pastholo, grid.Pastpres,
  2405. rep=1000, overlap.alternative = "lower",
  2406. rand.type=2,ncores=4)
  2407. # write p values of similarity test
  2408. p_SIM_DI = cbind("p.D_GR"=sim.testgr$p.D,"p.I_GR"=sim.testgr$p.I,"p.D_LW"=sim.testlw$p.D,"p.I_LW"=sim.testlw$p.D)
  2409. write.csv(p_SIM_DI,"presholoPast_SIM_Test.csv",row.names=FALSE)
  2410. p_SIM_DI
  2411. #p.D_GR p.I_GR p.D_LW p.I_LW
  2412. # Plot test distributions
  2413. ecospat.plot.overlap.test(eq.testgr, "D", "Greater Equivalency")
  2414. ecospat.plot.overlap.test(eq.testlw, "D", "Lower Equivalency")
  2415. ecospat.plot.overlap.test(sim.testgr, "D", "Greater Similarity")
  2416. ecospat.plot.overlap.test(sim.testlw, "D", "Lower Similarity")
  2417. ## Plot niche space for first (grid.climholo) and second (grid.climpres) intervals
  2418. ecospat.plot.niche (grid.Pastpres, title='Pastpres', name.axis1='PC1', name.axis2='PC2', cor=FALSE)
  2419. ecospat.plot.niche (grid.Pastholo, title='Pastholo', name.axis1='PC1', name.axis2='PC2')
  2420. ## Plot niche overlap
  2421. ecospat.plot.niche.dyn(z1 = grid.Pastholo, z2 = grid.Pastpres, quant=0.25, interest=2,
  2422. title= "P. ast Holo to Pres", name.axis1="PC1",
  2423. name.axis2="PC2", col.unf = "#313695", col.exp = "#abd9d9", col.stab = '#74add1', colZ1 =
  2424. "#313695", colZ2 = "#abd9d9", transparency = 40)
  2425. ecospat.shift.centroids(sp1 = scores.spholo, sp2 = scores.sppres, scores.climholo, scores.climpres, col = 'white')
  2426. rstudioapi::savePlotAsImage("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/PAST/masked/maskedtwice/Ecospat_past_10_2_24/figures/P. ast Holo to Pres.png",width=1000,height=750)
  2427. #___________________________
  2428. ### Look at niche expantion, stability, and unfilling
  2429. # NA=analysis on entire area, 0=analysis on only overlapping, 0.05=analysis on 5th quantile intersection
  2430. dynam_allAreas = ecospat.niche.dyn.index (z1 = grid.Pastholo, z2 = grid.Pastpres, intersection=NA)
  2431. dynam_overlap = ecospat.niche.dyn.index (z1 = grid.Pastholo, z2 = grid.Pastpres, intersection=0)
  2432. # write csv of niche dynmaic percentages
  2433. Niche_Ex_St = cbind("AllAreas"=dynam_allAreas$dynamic.index.w,
  2434. "Overlapping"=dynam_overlap$dynamic.index.w)
  2435. Niche_Ex_St
  2436. write.csv(Niche_Ex_St,"GlycymDynamicsPastholopres.csv",row.names=TRUE)
  2437. #################&&&&&&&&&&&&&&&&&&&&&############ ENM #################
  2438. ########################################## ACER PRES ENM ################################
  2439. ##### Loading in the Data --------------------------------------------------------------------------------------------------
  2440. # master background file;
  2441. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/ACERV/masked/Master_files_acerv_add_mask")
  2442. All.back <- read.csv('masterall.background.csv', header=T)
  2443. #filter to time period background
  2444. pres.back <- All.back %>% filter(time.bin== c('Present'))
  2445. Holo.back <- All.back %>% filter(time.bin=='Holocene')
  2446. RCP452050.back <- All.back %>% filter(time.bin=='RCP452050')
  2447. RCP852050.back <- All.back %>% filter(time.bin=='RCP852050')
  2448. RCP452100.back <- All.back %>% filter(time.bin=='RCP452100')
  2449. RCP852100.back <- All.back %>% filter(time.bin=='RCP852100')
  2450. #save background I am using
  2451. write.csv(pres.back, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/ACERV/masked/models_Acerv_pres_add_mask/pres_back.csv", row.names=FALSE)
  2452. # master occurrence file;
  2453. all.occ <- read.csv('masterall.occs.csv', header=T)
  2454. #reading in specific time period files
  2455. pres.occs <- read.csv('masterpres.occs.csv', header=T)
  2456. #check if background and occurance have same column names
  2457. identical(colnames(pres.back), colnames(pres.occs))
  2458. ##### Setting up the models ------------------------------------------------------------------------------------------------
  2459. # create null df - empty dataframe that null data will go into later
  2460. pres.null <- create.null.df('Acervicornis', 'Present', 'Caribbean') #function(taxon.name, time.bin, extent){
  2461. # create summary df
  2462. pres.summary <- create.summary.df('Acervicornis', 'Present', 'Caribbean')
  2463. create.folders.for.maxent(pres.summary)
  2464. # run null model
  2465. Acerv.null <- null.aic(null.df = pres.null,
  2466. occs = pres.occs,
  2467. background = pres.back,
  2468. first.occ.col = 10)
  2469. ##### Optimizing Model Parameters ------------------------------------------------------------------------------------------
  2470. # find most optimized model
  2471. Acerv.optim <- optimize.maxent.likelihood(pres.summary, # name of the output summary file
  2472. occs = pres.occs, # species occurrences
  2473. background = pres.back, # background for the pres
  2474. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  2475. first.occ.col = 10)
  2476. View(Acerv.optim)
  2477. #want model to be at least more than 2 AICc lower than the null
  2478. #also plan to check pROC and response curves to pick best model
  2479. write.csv(Acerv.optim, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/ACERV/masked/models_Acerv_pres_add_mask/Acerv_optim.csv", row.names=FALSE)
  2480. ### CHECK RESPONSE CURVES FOR REALISM!!!!!
  2481. ##### Running Cross-Validation ---------------------------------------------------------------------------------------------
  2482. ### LQP 0.10
  2483. # create eval object
  2484. # default f.class = LQP, so if f.class argument is missing, will assume LQP; only need it there in case NOT LQP
  2485. Acervpres.eval_LQP0.10 <- create.eval.df('Acerv', 'Present', 'Caribbean', beta.values = 0.10, f.class = 'LQP')
  2486. Acervpres.eval_LQP0.10
  2487. # create folders for Baculites in the Cenomanian
  2488. create.folders.for.maxent(Acervpres.eval_LQP0.10)
  2489. # run eval object
  2490. Acervpres.eval_LQP0.10 <- maxent.crossval.error(eval.df = Acervpres.eval_LQP0.10,
  2491. occs = pres.occs, # species occurrences
  2492. background = pres.back, # background for the pres
  2493. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  2494. first.occ.col = 10,
  2495. first.test.col = 16,
  2496. omission.rate = 0.025, #express as proportion
  2497. all.background = All.back)
  2498. #these results go into the folders that are only 4 of the 5 abcde (ex abcd, acde etc.)
  2499. # response curves good
  2500. ### LQP 0.25
  2501. Acervpres.eval_LQP0.25 <- create.eval.df('Acerv', 'Present', 'Caribbean', beta.values = 0.25, f.class = 'LQP')
  2502. Acervpres.eval_LQP0.25
  2503. # create folders
  2504. create.folders.for.maxent(Acervpres.eval_LQP0.25)
  2505. # run eval object
  2506. Acervpres.eval_LQP0.25 <- maxent.crossval.error(eval.df = Acervpres.eval_LQP0.25,
  2507. occs = pres.occs, # species occurrences
  2508. background = pres.back, # background for the pres
  2509. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  2510. first.occ.col = 10,
  2511. first.test.col = 16,
  2512. omission.rate = 0, #express as proportion
  2513. all.background = All.back)
  2514. #response curves similar- not as good, donmt go down as far
  2515. ### analyzing summary files
  2516. ## if running multiple eval models, check for:
  2517. # 1.) does one model setting have systematically higher omission rates?
  2518. # 2.) do the lambdas of one model change a lot more between cross-validation reps than another model type?
  2519. # 3.) do the response curves of one model look non-sensical? check all 5 cross-validation reps
  2520. Acervpres.eval_LQP0.10$summary # pROC 1.672626
  2521. Acervpres.eval_LQP0.25$summary # pROC 1.662092
  2522. # going with LQP 0.10
  2523. ##### Evaluate Model, Calculate Threshold and Model Variability ------------------------------------------------------------
  2524. ### LQP 0.10
  2525. # evaluate model to calculate weighted suitibility and stdev
  2526. Acervpres.means_LQP0.10 <- maxent.eval(eval = Acervpres.eval_LQP0.10)
  2527. thresh = min(Acervpres.means_LQP0.10$occ$w.mean)
  2528. print(thresh)
  2529. # this is the threshold
  2530. # save this value!!
  2531. ### plot model suitability/uncertainty plots
  2532. # the only input you need is the object made from the maxent.eval function
  2533. suit.uncert.plot(Acervpres.eval_LQP0.10)
  2534. ggsave('Acervpres.eval_LQP0.10.pdf')
  2535. ##### Projecting Model to all extents --------------------------------------------------------------------------------------
  2536. Acervpres.thresh_LQP0.10 <- 0.001166019
  2537. Acervpres.everything_LQP0.10 <- maxent.everything(eval = Acervpres.eval_LQP0.10,
  2538. thresh = Acervpres.thresh_LQP0.10,
  2539. means = Acervpres.means_LQP0.10,
  2540. everything= All.back,
  2541. predic = 6:9)
  2542. View(Acervpres.everything_LQP0.10)
  2543. ##### Running Informed MESS Analysis ---------------------------------------------------------------------------------------
  2544. # defining the tolerance vector
  2545. # 1 = can extrapolate to non-analog conditions
  2546. # 0 = cannot extrapolate to non-analog conditions
  2547. Acerv.tolerance <- c(1,1, # max salinity
  2548. 1,1, # max temp
  2549. 1,1, # range salinity
  2550. 1,1) # range temp
  2551. ################### running mess holocene
  2552. Acerv.mess.Holo <- informed.mess(ref.extent = pres.back,
  2553. mess.extent = Holo.back, #maybe they are crazy high because project to same, lets try diff
  2554. coord.cols = 2:3,
  2555. predic = 6:9,
  2556. tolerance = Acerv.tolerance)
  2557. ################### running mess 45 2050
  2558. Acerv.mess.452050 <- informed.mess(ref.extent = pres.back,
  2559. mess.extent = RCP452050.back, #maybe they are crazy high because project to same, lets try diff
  2560. coord.cols = 2:3,
  2561. predic = 6:9,
  2562. tolerance = Acerv.tolerance)
  2563. ################### running mess 45 2100
  2564. Acerv.mess.452100 <- informed.mess(ref.extent = pres.back,
  2565. mess.extent = RCP452100.back, #maybe they are crazy high because project to same, lets try diff
  2566. coord.cols = 2:3,
  2567. predic = 6:9,
  2568. tolerance = Acerv.tolerance)
  2569. ################### running mess 85 2050
  2570. Acerv.mess.852050 <- informed.mess(ref.extent = pres.back,
  2571. mess.extent = RCP852050.back, #maybe they are crazy high because project to same, lets try diff
  2572. coord.cols = 2:3,
  2573. predic = 6:9,
  2574. tolerance = Acerv.tolerance)
  2575. ################### running mess 85 2100
  2576. Acerv.mess.852100 <- informed.mess(ref.extent = pres.back,
  2577. mess.extent = RCP852100.back, #maybe they are crazy high because project to same, lets try diff
  2578. coord.cols = 2:3,
  2579. predic = 6:9,
  2580. tolerance = Acerv.tolerance)
  2581. #### Acerv mess all
  2582. Acerv.mess.all <- informed.mess(ref.extent = pres.back,
  2583. mess.extent = All.back,
  2584. coord.cols = 2:3,
  2585. predic = 6:9,
  2586. tolerance = Acerv.tolerance)
  2587. ##### Saving Everything ----------------------------------------------------------------------------------------------------
  2588. pres.output <- All.back %>% dplyr::select('Name', 'long', 'lat', 'time.bin')
  2589. pres.output <- cbind(pres.output,Acervpres.everything_LQP0.10)
  2590. pres.output$Name <- 'Acervicornis'
  2591. pres.with.mess <- cbind(pres.output, Acerv.mess.all)
  2592. write.csv(pres.output, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/ACERV/masked/models_Acerv_pres_add_mask/pres.output.all.csv", row.names = F)
  2593. # null model
  2594. write.csv(Acerv.null, 'Acerv.null.csv', row.names = F)
  2595. # model optimized summary object
  2596. write.csv(Acerv.optim, 'Acerv.optim.summary.csv', row.names = F)
  2597. # model projected to all extents
  2598. write.csv(Acervpres.everything_LQP0.10, 'Acerv.LQP0.10.csv', row.names = F)
  2599. # model mess analysis
  2600. write.csv(Acerv.mess.Holo, 'Acerv.mess.Holo.csv', row.names = F)
  2601. write.csv(Acerv.mess.452050, 'Acerv.mess.452050.csv', row.names = F)
  2602. write.csv(Acerv.mess.452100, 'Acerv.mess.452100.csv', row.names = F)
  2603. write.csv(Acerv.mess.852050, 'Acerv.mess.852050.csv', row.names = F)
  2604. write.csv(Acerv.mess.852100, 'Acerv.mess.852100.csv', row.names = F)
  2605. ########################################## ACER HOLO ENM ################################
  2606. # master background file;
  2607. All.back <- read.csv('masterall.background.csv', header=T)
  2608. pres.back <- All.back %>% filter(time.bin=='Present')
  2609. Holo.back <- All.back %>% filter(time.bin=='Holocene')
  2610. RCP452050.back <- All.back %>% filter(time.bin=='RCP452050')
  2611. RCP852050.back <- All.back %>% filter(time.bin=='RCP852050')
  2612. RCP452100.back <- All.back %>% filter(time.bin=='RCP452100')
  2613. RCP852100.back <- All.back %>% filter(time.bin=='RCP852100')
  2614. #save background I am using
  2615. write.csv(Holo.back, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/ACERV/masked/maskedtwice/models_Acerv_Holo_add_mask/Holo_back.csv", row.names=FALSE)
  2616. # master occurrence file;
  2617. all.occ <- read.csv('masterall.occs.csv', header=T)
  2618. #reading in specific time period files
  2619. Pres.occs <- read.csv('masterpres.occs.csv', header=T)
  2620. Holo.occs <- read.csv('masterholo.occs.csv', header=T)
  2621. #check if background and occurance have same column names
  2622. identical(colnames(Holo.back), colnames(Holo.occs))
  2623. ##### Setting up the models ------------------------------------------------------------------------------------------------
  2624. # create null df - empty dataframe that null data will go into later
  2625. Holo.null <- create.null.df('Acervicornis', 'Holocene', 'Caribbean') #function(taxon.name, time.bin, extent)
  2626. # create summary df
  2627. Holo.summary <- create.summary.df('Acervicornis', 'Holocene', 'Caribbean')
  2628. create.folders.for.maxent(Holo.summary)
  2629. # run null model
  2630. Acerv.null <- null.aic(null.df = Holo.null,
  2631. occs = Holo.occs,
  2632. background = Holo.back,
  2633. first.occ.col = 10)
  2634. ##### Optimizing Model Parameters ------------------------------------------------------------------------------------------
  2635. # find most optimized model
  2636. Acerv.optim <- optimize.maxent.likelihood(Holo.summary, # name of the output summary file
  2637. occs = Holo.occs, # species occurrences
  2638. background = Holo.back, # background for the Holo
  2639. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  2640. first.occ.col = 10)
  2641. View(Acerv.optim)
  2642. #want model to be at least more than 2 AICc lower than the null
  2643. #also plan to check pROC and response curves to pick best model
  2644. write.csv(Acerv.optim, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/ACERV/masked/maskedtwice/models_Acerv_Holo_add_mask/Acerv_optim.csv", row.names=FALSE)
  2645. ### CHECK RESPONSE CURVES FOR REALISM!!!!!
  2646. ##### Running Cross-Validation ---------------------------------------------------------------------------------------------
  2647. ### Q 0.05
  2648. # create eval object
  2649. # default f.class = Q, so if f.class argument is missing, will assume LQP; only need it there in case NOT LQP
  2650. AcervHolo.eval_Q0.05 <- create.eval.df('Acerv', 'Holocene', 'Caribbean', beta.values = 0.05, f.class = 'Q')
  2651. AcervHolo.eval_Q0.05
  2652. # create folders for Baculites in the Cenomanian
  2653. create.folders.for.maxent(AcervHolo.eval_Q0.05)
  2654. # run eval object
  2655. AcervHolo.eval_Q0.05 <- maxent.crossval.error(eval.df = AcervHolo.eval_Q0.05,
  2656. occs = Holo.occs, # species occurrences
  2657. background = Holo.back, # background for the Holo
  2658. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  2659. first.occ.col = 10,
  2660. first.test.col = 16,
  2661. omission.rate = 0, #express as proportion
  2662. all.background = All.back)
  2663. #these results go into the folders that are only 4 of the 5 abcde (ex abcd, acde etc.)
  2664. # WORKED!!!! curves are curves!!!!!!! or at least temp is curves
  2665. ### Q0.025
  2666. AcervHolo.eval_Q0.025 <- create.eval.df('Acerv', 'Holocene', 'Caribbean', beta.values = 0.025, f.class = 'Q')
  2667. AcervHolo.eval_Q0.025
  2668. # create folders
  2669. create.folders.for.maxent(AcervHolo.eval_Q0.025)
  2670. # run eval object
  2671. AcervHolo.eval_Q0.025 <- maxent.crossval.error(eval.df = AcervHolo.eval_Q0.025,
  2672. occs = Holo.occs, # species occurrences
  2673. background = Holo.back, # background for the Holo
  2674. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  2675. first.occ.col = 10,
  2676. first.test.col = 16,
  2677. omission.rate = 0, #express as proportion
  2678. all.background = All.back)
  2679. #curves are not as good going with other
  2680. #still a good model compared to null and has good curves
  2681. ### Q 0.10
  2682. AcervHolo.eval_LQP0.025 <- create.eval.df('Acerv', 'Holocene', 'Caribbean', beta.values = 0.025, f.class = 'LQP')
  2683. AcervHolo.eval_LQP0.025
  2684. # create folders
  2685. create.folders.for.maxent(AcervHolo.eval_LQP0.025)
  2686. # run eval object
  2687. AcervHolo.eval_LQP0.025 <- maxent.crossval.error(eval.df = AcervHolo.eval_LQP0.025,
  2688. occs = Holo.occs, # species occurrences
  2689. background = Holo.back, # background for the Holo
  2690. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  2691. first.occ.col = 10,
  2692. first.test.col = 16,
  2693. omission.rate = 0, #express as proportion
  2694. all.background = All.back)
  2695. ### analyzing summary files
  2696. ## if running multiple eval models, check for:
  2697. # 1.) does one model setting have systematically higher omission rates?
  2698. # 2.) do the lambdas of one model change a lot more between cross-validation reps than another model type?
  2699. # 3.) do the response curves of one model look non-sensical? check all 5 cross-validation reps
  2700. AcervHolo.eval_Q0.025$summary # 1.823454
  2701. AcervHolo.eval_Q0.05$summary # 1.821950
  2702. AcervHolo.eval_LQP0.025$summary #1.887521
  2703. # neither mode seems to be systematically better basically identical, i will do LQP0.025
  2704. ##### Evaluate Model, Calculate Threshold and Model Variability ------------------------------------------------------------
  2705. ### Q 0.10
  2706. # evaluate model to calculate weighted suitibility and stdev
  2707. AcervHolo.means_LQP0.025 <- maxent.eval(eval = AcervHolo.eval_LQP0.025)
  2708. thresh = min(AcervHolo.means_LQP0.025$occ$w.mean)
  2709. print(thresh)
  2710. # 0.08827532
  2711. # this is the threshold
  2712. # save this value!!
  2713. ### Q 0.5
  2714. ### plot model suitability/uncertainty plots
  2715. # the only input you need is the object made from the maxent.eval function
  2716. suit.uncert.plot(AcervHolo.eval_LQP0.025)
  2717. ggsave('AcervHolo.eval_LQP0.025.pdf')
  2718. ### deciding to go with Q 0.10 since it has slightly more realistic response curves
  2719. ##### Projecting Model to all extents --------------------------------------------------------------------------------------
  2720. AcervHolo.thresh_LQP0.025 <- 0.08827532
  2721. AcervHolo.everything_LQP0.025 <- maxent.everything(eval = AcervHolo.eval_LQP0.025,
  2722. thresh = AcervHolo.thresh_LQP0.025,
  2723. means = AcervHolo.means_LQP0.025,
  2724. everything= All.back,
  2725. predic = 6:9)
  2726. View(AcervHolo.everything_LQP0.025)
  2727. ##### Running Informed MESS Analysis ---------------------------------------------------------------------------------------
  2728. # defining the tolerance vector
  2729. # 1 = can extrapolate to non-analog conditions
  2730. # 0 = cannot extrapolate to non-analog conditions
  2731. Acerv.tolerance <- c(1,1, # max salinity
  2732. 1,1, # max temp
  2733. 1,1, # range salinity
  2734. 1,0) # range temp
  2735. ################### running mess present
  2736. Acerv.mess.pres <- informed.mess(ref.extent = Holo.back,
  2737. mess.extent = pres.back, #maybe they are crazy high because project to same, lets try diff
  2738. coord.cols = 2:3,
  2739. predic = 6:9,
  2740. tolerance = Acerv.tolerance)
  2741. ################### running mess 45 2050
  2742. Acerv.mess.452050 <- informed.mess(ref.extent = Holo.back,
  2743. mess.extent = RCP452050.back, #maybe they are crazy high because project to same, lets try diff
  2744. coord.cols = 2:3,
  2745. predic = 6:9,
  2746. tolerance = Acerv.tolerance)
  2747. ################### running mess 45 2100
  2748. Acerv.mess.452100 <- informed.mess(ref.extent = Holo.back,
  2749. mess.extent = RCP452100.back, #maybe they are crazy high because project to same, lets try diff
  2750. coord.cols = 2:3,
  2751. predic = 6:9,
  2752. tolerance = Acerv.tolerance)
  2753. ################### running mess 85 2050
  2754. Acerv.mess.852050 <- informed.mess(ref.extent = Holo.back,
  2755. mess.extent = RCP852050.back, #maybe they are crazy high because project to same, lets try diff
  2756. coord.cols = 2:3,
  2757. predic = 6:9,
  2758. tolerance = Acerv.tolerance)
  2759. ################### running mess 85 2100
  2760. Acerv.mess.852100 <- informed.mess(ref.extent = Holo.back,
  2761. mess.extent = RCP852100.back, #maybe they are crazy high because project to same, lets try diff
  2762. coord.cols = 2:3,
  2763. predic = 6:9,
  2764. tolerance = Acerv.tolerance)
  2765. #mess all
  2766. Acerv.mess.all <- informed.mess(ref.extent = Holo.back,
  2767. mess.extent = All.back, #maybe they are crazy high because project to same, lets try diff
  2768. coord.cols = 2:3,
  2769. predic = 6:9,
  2770. tolerance = Acerv.tolerance)
  2771. ##### Saving Everything ----------------------------------------------------------------------------------------------------
  2772. pres.output <- All.back %>% dplyr::select('Name', 'long', 'lat', 'time.bin')
  2773. pres.output <- cbind(pres.output, AcervHolo.everything_LQP0.025)
  2774. pres.output$Name <- 'Acervicornis'
  2775. pres.with.mess <- cbind(pres.output, Acerv.mess.all)
  2776. write.csv(pres.output, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/ACERV/masked/maskedtwice/models_Acerv_Holo_add_mask/pres.output.all.csv", row.names = F)
  2777. # null model
  2778. write.csv(Acerv.null, 'Acerv.null.csv', row.names = F)
  2779. # model optimized summary object
  2780. write.csv(Acerv.optim, 'Acerv.optim.summary.csv', row.names = F)
  2781. # model projected to all extents
  2782. write.csv(AcervHolo.everything_LQP0.025, 'Acerv.LQP0.025.csv', row.names = F)
  2783. # model mess analysis
  2784. write.csv(Acerv.mess.pres, 'Acerv.mess.pres.csv', row.names = F)
  2785. write.csv(Acerv.mess.452050, 'Acerv.mess.452050.csv', row.names = F)
  2786. write.csv(Acerv.mess.452100, 'Acerv.mess.452100.csv', row.names = F)
  2787. write.csv(Acerv.mess.852050, 'Acerv.mess.852050.csv', row.names = F)
  2788. write.csv(Acerv.mess.852100, 'Acerv.mess.852100.csv', row.names = F)
  2789. ######################################### APAL PRES ENM ############
  2790. ##### Loading in the Data --------------------------------------------------------------------------------------------------
  2791. # master background file;
  2792. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/Master_files_apal_add_mask")
  2793. All.back <- read.csv('masterall.background.csv', header=T)
  2794. #filter to time period background
  2795. pres.back <- All.back %>% filter(time.bin== c('Present'))
  2796. Holo.back <- All.back %>% filter(time.bin=='Holocene')
  2797. RCP452050.back <- All.back %>% filter(time.bin=='RCP452050')
  2798. RCP852050.back <- All.back %>% filter(time.bin=='RCP852050')
  2799. RCP452100.back <- All.back %>% filter(time.bin=='RCP452100')
  2800. RCP852100.back <- All.back %>% filter(time.bin=='RCP852100')
  2801. #save background I am using
  2802. write.csv(pres.back, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/models_Apal_pres_add_mask/pres_back.csv", row.names=FALSE)
  2803. # master occurrence file;
  2804. all.occ <- read.csv('masterall.occs.csv', header=T)
  2805. #reading in specific time period files
  2806. pres.occs <- read.csv('masterpres.occs.csv', header=T)
  2807. #check if background and occurance have same column names
  2808. identical(colnames(pres.back), colnames(pres.occs))
  2809. ##### Setting up the models ------------------------------------------------------------------------------------------------
  2810. # working directory for models
  2811. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/models_Apal_pres_add_mask")
  2812. # create null df - empty dataframe that null data will go into later
  2813. pres.null <- create.null.df('Apalmata', 'Present', 'Caribbean') #function(taxon.name, time.bin, extent){
  2814. # create summary df
  2815. pres.summary <- create.summary.df('Apalmata', 'Present', 'Caribbean')
  2816. create.folders.for.maxent(pres.summary)
  2817. # run null model
  2818. Apal.null <- null.aic(null.df = pres.null,
  2819. occs = pres.occs,
  2820. background = pres.back,
  2821. first.occ.col = 10)
  2822. ##### Optimizing Model Parameters ------------------------------------------------------------------------------------------
  2823. # find most optimized model
  2824. Apal.optim <- optimize.maxent.likelihood(pres.summary, # name of the output summary file
  2825. occs = pres.occs, # species occurrences
  2826. background = pres.back, # background for the pres
  2827. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  2828. first.occ.col = 10)
  2829. View(Apal.optim)
  2830. #want model to be at least more than 2 AICc lower than the null
  2831. #also plan to check pROC and response curves to pick best model
  2832. write.csv(Apal.optim, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/models_Apal_pres_add_mask/Apal_optim.csv", row.names=FALSE)
  2833. ### CHECK RESPONSE CURVES FOR REALISM!!!!!
  2834. ##### Running Cross-Validation ---------------------------------------------------------------------------------------------
  2835. ### LQP .05
  2836. # create eval object
  2837. # default f.class = LQP, so if f.class argument is missing, will assume LQP; only need it there in case NOT LQP
  2838. Apalpres.eval_LQP0.05 <- create.eval.df('Apal', 'Present', 'Caribbean', beta.values = 0.05, f.class = 'LQP')
  2839. Apalpres.eval_LQP0.05
  2840. # create folders for Baculites in the Cenomanian
  2841. create.folders.for.maxent(Apalpres.eval_LQP0.05)
  2842. # run eval object
  2843. Apalpres.eval_LQP0.05 <- maxent.crossval.error(eval.df = Apalpres.eval_LQP0.05,
  2844. occs = pres.occs, # species occurrences
  2845. background = pres.back, # background for the pres
  2846. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  2847. first.occ.col = 10,
  2848. first.test.col = 16,
  2849. omission.rate = 0, #express as proportion
  2850. all.background = All.back)
  2851. #these results go into the folders that are only 4 of the 5 abcde (ex abcd, acde etc.)
  2852. # response curves good max temp has a true hump that goes all the way down, only range tamp increases to lower ranges but that makes perfect sense right?
  2853. ### LQP 0.025
  2854. Apalpres.eval_LQP0.025 <- create.eval.df('Apal', 'Present', 'Caribbean', beta.values = 0.025, f.class = 'LQP')
  2855. Apalpres.eval_LQP0.025
  2856. # create folders
  2857. create.folders.for.maxent(Apalpres.eval_LQP0.025)
  2858. # run eval object
  2859. Apalpres.eval_LQP0.025 <- maxent.crossval.error(eval.df = Apalpres.eval_LQP0.025,
  2860. occs = pres.occs, # species occurrences
  2861. background = pres.back, # background for the pres
  2862. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  2863. first.occ.col = 10,
  2864. first.test.col = 16,
  2865. omission.rate = 0, #express as proportion
  2866. all.background = All.back)
  2867. #response curves similar- only thing is max temp starts going back down at high temps but not all the way.
  2868. ### analyzing summary files
  2869. ## if running multiple eval models, check for:
  2870. # 1.) does one model setting have systematically higher omission rates?
  2871. # 2.) do the lambdas of one model change a lot more between cross-validation reps than another model type?
  2872. # 3.) do the response curves of one model look non-sensical? check all 5 cross-validation reps
  2873. Apalpres.eval_LQP0.05$summary # pROC 1.690565
  2874. Apalpres.eval_LQP0.025$summary # pROC 1.685479
  2875. # going with LQP 0.025 since slightly higher pROC?? im not sure which is better?
  2876. ##### Evaluate Model, Calculate Threshold and Model Variability ------------------------------------------------------------
  2877. ### LQP 0.025
  2878. # evaluate model to calculate weighted suitibility and stdev
  2879. Apalpres.means_LQP0.025 <- maxent.eval(eval = Apalpres.eval_LQP0.025)
  2880. thresh = min(Apalpres.means_LQP0.025$occ$w.mean)
  2881. print(thresh)
  2882. # 0.2613874
  2883. # this is the threshold
  2884. # save this value!!
  2885. ### Q 0.5
  2886. ### plot model suitability/uncertainty plots
  2887. # the only input you need is the object made from the maxent.eval function
  2888. suit.uncert.plot(Apalpres.eval_LQP0.025)
  2889. ggsave('Apalpres.eval_LQP0.025.pdf')
  2890. ### deciding to go with Q 2.0 since it has slightly more realistic response curves
  2891. ##### Projecting Model to all extents --------------------------------------------------------------------------------------
  2892. Apalpres.thresh_LQP0.025 <- 0.2613874
  2893. Apalpres.everything_LQP0.025 <- maxent.everything(eval = Apalpres.eval_LQP0.025,
  2894. thresh = Apalpres.thresh_LQP0.025,
  2895. means = Apalpres.means_LQP0.025,
  2896. everything= All.back,
  2897. predic = 6:9)
  2898. View(Apalpres.everything_LQP0.025)
  2899. ##### Running Informed MESS Analysis ---------------------------------------------------------------------------------------
  2900. # defining the tolerance vector
  2901. # 1 = can extrapolate to non-analog conditions
  2902. # 0 = cannot extrapolate to non-analog conditions
  2903. Apal.tolerance <- c(1,1, # max salinity
  2904. 1,1, # max temp
  2905. 1,1, # range salinity
  2906. 1,1) # range temp
  2907. ################## running mess holocene
  2908. Apal.mess.Holo <- informed.mess(ref.extent = pres.back,
  2909. mess.extent = Holo.back, #maybe they are crazy high because project to same, lets try diff
  2910. coord.cols = 2:3,
  2911. predic = 6:9,
  2912. tolerance = Apal.tolerance)
  2913. ################### running mess 45 2050
  2914. Apal.mess.452050 <- informed.mess(ref.extent = pres.back,
  2915. mess.extent = RCP452050.back, #maybe they are crazy high because project to same, lets try diff
  2916. coord.cols = 2:3,
  2917. predic = 6:9,
  2918. tolerance = Apal.tolerance)
  2919. ################### running mess 45 2100
  2920. Apal.mess.452100 <- informed.mess(ref.extent = pres.back,
  2921. mess.extent = RCP452100.back, #maybe they are crazy high because project to same, lets try diff
  2922. coord.cols = 2:3,
  2923. predic = 6:9,
  2924. tolerance = Apal.tolerance)
  2925. ################### running mess 85 2050
  2926. Apal.mess.852050 <- informed.mess(ref.extent = pres.back,
  2927. mess.extent = RCP852050.back, #maybe they are crazy high because project to same, lets try diff
  2928. coord.cols = 2:3,
  2929. predic = 6:9,
  2930. tolerance = Apal.tolerance)
  2931. ################### running mess 85 2100
  2932. Apal.mess.852100 <- informed.mess(ref.extent = pres.back,
  2933. mess.extent = RCP852100.back, #maybe they are crazy high because project to same, lets try diff
  2934. coord.cols = 2:3,
  2935. predic = 6:9,
  2936. tolerance = Apal.tolerance)
  2937. #### apal mess all
  2938. Apal.mess.all <- informed.mess(ref.extent = pres.back,
  2939. mess.extent = All.back, #maybe they are crazy high because project to same, lets try diff
  2940. coord.cols = 2:3,
  2941. predic = 6:9,
  2942. tolerance = Apal.tolerance)
  2943. ##### Saving Everything ----------------------------------------------------------------------------------------------------
  2944. apal.output <- All.back %>% dplyr::select('Name', 'long', 'lat', 'time.bin')
  2945. apal.output <- cbind(apal.output, Apalpres.everything_LQP0.025)
  2946. apal.output$Name <- 'Apalmata'
  2947. apal.with.mess <- cbind(apal.output, Apal.mess.all)
  2948. write.csv(apal.with.mess, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/models_Apal_pres_add_mask/apal.output.all.csv", row.names = F)
  2949. # null model
  2950. write.csv(Apal.null, 'Apal.null.csv', row.names = F)
  2951. # model optimized summary object
  2952. write.csv(Apal.optim, 'Apal.optim.summary.csv', row.names = F)
  2953. # model projected to all extents
  2954. write.csv(Apalpres.everything_LQP0.025, 'Apal.LQP0.025.csv', row.names = F)
  2955. # model mess analysis
  2956. write.csv(Apal.mess.Holo, 'Apal.mess.Holo.csv', row.names = F)
  2957. write.csv(Apal.mess.452050, 'Apal.mess.452050.csv', row.names = F)
  2958. write.csv(Apal.mess.452100, 'Apal.mess.452100.csv', row.names = F)
  2959. write.csv(Apal.mess.852050, 'Apal.mess.852050.csv', row.names = F)
  2960. write.csv(Apal.mess.852100, 'Apal.mess.852100.csv', row.names = F)
  2961. ####################################### APAL HOLO ENM #############
  2962. ##### Loading in the Data --------------------------------------------------------------------------------------------------
  2963. # master background file;
  2964. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/maskedtwice/Master_files_apal_add_mask")
  2965. All.back <- read.csv('masterall.background.csv', header=T)
  2966. #filter to time period background
  2967. LGM.back <- All.back %>% filter(time.bin== c('LGM'))
  2968. pres.back <- All.back %>% filter(time.bin=='Present')
  2969. Holo.back <- All.back %>% filter(time.bin=='Holocene')
  2970. Holo2.back <- All.back %>% filter(time.bin=='Holocene2')
  2971. RCP452050.back <- All.back %>% filter(time.bin=='RCP452050')
  2972. RCP852050.back <- All.back %>% filter(time.bin=='RCP852050')
  2973. RCP452100.back <- All.back %>% filter(time.bin=='RCP452100')
  2974. RCP852100.back <- All.back %>% filter(time.bin=='RCP852100')
  2975. #save background I am using
  2976. write.csv(Holo.back, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/maskedtwice/models_Apal_Holo_add_mask/Holo_back.csv", row.names=FALSE)
  2977. # master occurrence file;
  2978. all.occ <- read.csv('masterall.occs.csv', header=T)
  2979. #reading in specific time period files
  2980. Pres.occs <- read.csv('masterpres.occs.csv', header=T)
  2981. Holo.occs <- read.csv('masterholo.occs.csv', header=T)
  2982. #check if background and occurance have same column names
  2983. identical(colnames(Holo.back), colnames(Holo.occs))
  2984. ##### Setting up the models ------------------------------------------------------------------------------------------------
  2985. # create null df - empty dataframe that null data will go into later
  2986. Holo.null <- create.null.df('Apalmata', 'Holocene', 'Caribbean') #function(taxon.name, time.bin, extent)
  2987. # create summary df
  2988. Holo.summary <- create.summary.df('Apalmata', 'Holocene', 'Caribbean')
  2989. create.folders.for.maxent(Holo.summary)
  2990. # run null model
  2991. Apal.null <- null.aic(null.df = Holo.null,
  2992. occs = Holo.occs,
  2993. background = Holo.back,
  2994. first.occ.col = 10)
  2995. ##### Optimizing Model Parameters ------------------------------------------------------------------------------------------
  2996. # find most optimized model
  2997. Apal.optim <- optimize.maxent.likelihood(Holo.summary, # name of the output summary file
  2998. occs = Holo.occs, # species occurrences
  2999. background = Holo.back, # background for the Holo
  3000. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  3001. first.occ.col = 10)
  3002. View(Apal.optim)
  3003. #want model to be at least more than 2 AICc lower than the null
  3004. #also plan to check pROC and response curves to pick best model
  3005. write.csv(Apal.optim, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/maskedtwice/models_Apal_Holo_add_mask/Apal_optim.csv", row.names=FALSE)
  3006. ### CHECK RESPONSE CURVES FOR REALISM!!!!!
  3007. ##### Running Cross-Validation ---------------------------------------------------------------------------------------------
  3008. ### LQP 0.025
  3009. # create eval object
  3010. # default f.class = Q, so if f.class argument is missing, will assume LQP; only need it there in case NOT LQP
  3011. ApalHolo.eval_LQP0.025 <- create.eval.df('Apal', 'Holocene', 'Caribbean', beta.values = 0.025, f.class = 'LQP')
  3012. ApalHolo.eval_LQP0.025
  3013. # create folders for Baculites in the Cenomanian
  3014. create.folders.for.maxent(ApalHolo.eval_LQP0.025)
  3015. # run eval object
  3016. ApalHolo.eval_LQP0.025 <- maxent.crossval.error(eval.df = ApalHolo.eval_LQP0.025,
  3017. occs = Holo.occs, # species occurrences
  3018. background = Holo.back, # background for the Holo
  3019. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  3020. first.occ.col = 10,
  3021. first.test.col = 16,
  3022. omission.rate = 0, #express as proportion
  3023. all.background = All.back)
  3024. #these results go into the folders that are only 4 of the 5 abcde (ex abcd, acde etc.)
  3025. # WORKED!!!! curves are curves!!!!!!!
  3026. ### LQP 0.10
  3027. ApalHolo.eval_LQP0.10 <- create.eval.df('Apal', 'Holocene', 'Caribbean', beta.values = 0.10, f.class = 'LQP')
  3028. ApalHolo.eval_LQP0.10
  3029. # create folders
  3030. create.folders.for.maxent(ApalHolo.eval_LQP0.10)
  3031. # run eval object
  3032. ApalHolo.eval_LQP0.10 <- maxent.crossval.error(eval.df = ApalHolo.eval_LQP0.10,
  3033. occs = Holo.occs, # species occurrences
  3034. background = Holo.back, # background for the Holo
  3035. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  3036. first.occ.col = 10,
  3037. first.test.col = 16,
  3038. omission.rate = 0, #express as proportion
  3039. all.background = All.back)
  3040. #curves are not as good going with other
  3041. ### analyzing summary files
  3042. ## if running multiple eval models, check for:
  3043. # 1.) does one model setting have systematically higher omission rates?
  3044. # 2.) do the lambdas of one model change a lot more between cross-validation reps than another model type?
  3045. # 3.) do the response curves of one model look non-sensical? check all 5 cross-validation reps
  3046. ApalHolo.eval_LQP0.10$summary # 1.958130
  3047. ApalHolo.eval_LQP0.025$summary #1.971328
  3048. # neither mode seems to be systematically better basically identical, i will do LQP0.025
  3049. ##### Evaluate Model, Calculate Threshold and Model Variability ------------------------------------------------------------
  3050. ### Q 0.10
  3051. # evaluate model to calculate weighted suitibility and stdev
  3052. ApalHolo.means_LQP0.025 <- maxent.eval(eval = ApalHolo.eval_LQP0.025)
  3053. thresh = min(ApalHolo.means_LQP0.025$occ$w.mean)
  3054. print(thresh)
  3055. # 0.01926973
  3056. # this is the threshold
  3057. # save this value!!
  3058. ### plot model suitability/uncertainty plots
  3059. # the only input you need is the object made from the maxent.eval function
  3060. suit.uncert.plot(ApalHolo.eval_LQP0.025)
  3061. ggsave('ApalHolo.eval_LQP0.025.pdf')
  3062. ### deciding to go with Q 0.10 since it has slightly more realistic response curves
  3063. ##### Projecting Model to all extents --------------------------------------------------------------------------------------
  3064. ApalHolo.thresh_LQP0.025 <- 0.01926973
  3065. ApalHolo.everything_LQP0.025 <- maxent.everything(eval = ApalHolo.eval_LQP0.025,
  3066. thresh = ApalHolo.thresh_LQP0.025,
  3067. means = ApalHolo.means_LQP0.025,
  3068. everything= All.back,
  3069. predic = 6:9)
  3070. View(ApalHolo.everything_LQP0.025)
  3071. ##### Running Informed MESS Analysis ---------------------------------------------------------------------------------------
  3072. # defining the tolerance vector
  3073. # 1 = can extrapolate to non-analog conditions
  3074. # 0 = cannot extrapolate to non-analog conditions
  3075. Apal.tolerance <- c(1,1, # max salinity
  3076. 1,1, # max temp
  3077. 0,1, # range salinity
  3078. 1,1) # range temp
  3079. ################### running mess present
  3080. Apal.mess.pres <- informed.mess(ref.extent = Holo.back,
  3081. mess.extent = pres.back, #maybe they are crazy high because project to same, lets try diff
  3082. coord.cols = 2:3,
  3083. predic = 6:9,
  3084. tolerance = Apal.tolerance)
  3085. ################### running mess 45 2050
  3086. Apal.mess.452050 <- informed.mess(ref.extent = Holo.back,
  3087. mess.extent = RCP452050.back, #maybe they are crazy high because project to same, lets try diff
  3088. coord.cols = 2:3,
  3089. predic = 6:9,
  3090. tolerance = Apal.tolerance)
  3091. ################### running mess 45 2100
  3092. Apal.mess.452100 <- informed.mess(ref.extent = Holo.back,
  3093. mess.extent = RCP452100.back, #maybe they are crazy high because project to same, lets try diff
  3094. coord.cols = 2:3,
  3095. predic = 6:9,
  3096. tolerance = Apal.tolerance)
  3097. ################### running mess 85 2050
  3098. Apal.mess.852050 <- informed.mess(ref.extent = Holo.back,
  3099. mess.extent = RCP852050.back, #maybe they are crazy high because project to same, lets try diff
  3100. coord.cols = 2:3,
  3101. predic = 6:9,
  3102. tolerance = Apal.tolerance)
  3103. ################### running mess 85 2100
  3104. Apal.mess.852100 <- informed.mess(ref.extent = Holo.back,
  3105. mess.extent = RCP852100.back, #maybe they are crazy high because project to same, lets try diff
  3106. coord.cols = 2:3,
  3107. predic = 6:9,
  3108. tolerance = Apal.tolerance)
  3109. #### apal mess all
  3110. Apal.mess.all <- informed.mess(ref.extent = Holo.back,
  3111. mess.extent = All.back, #maybe they are crazy high because project to same, lets try diff
  3112. coord.cols = 2:3,
  3113. predic = 6:9,
  3114. tolerance = Apal.tolerance)
  3115. ##### Saving Everything ----------------------------------------------------------------------------------------------------
  3116. apal.output <- All.back %>% dplyr::select('Name', 'long', 'lat', 'time.bin')
  3117. apal.output <- cbind(apal.output, ApalHolo.everything_LQP0.025)
  3118. apal.output$Name <- 'Apalmata'
  3119. apal.with.mess <- cbind(apal.output, Apal.mess.all)
  3120. write.csv(apal.output, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/APAL/masked/maskedtwice/models_Apal_holo_add_mask/apal.output.all.csv", row.names = F)
  3121. # null model
  3122. write.csv(Apal.null, 'Apal.null.csv', row.names = F)
  3123. # model optimized summary object
  3124. write.csv(Apal.optim, 'Apal.optim.summary.csv', row.names = F)
  3125. # model projected to all extents
  3126. write.csv(ApalHolo.everything_LQP0.025, 'Apal.LQP0.025.csv', row.names = F)
  3127. # model mess analysis
  3128. write.csv(Apal.mess.pres, 'Apal.mess.pres.csv', row.names = F)
  3129. write.csv(Apal.mess.452050, 'Apal.mess.452050.csv', row.names = F)
  3130. write.csv(Apal.mess.452100, 'Apal.mess.452100.csv', row.names = F)
  3131. write.csv(Apal.mess.852050, 'Apal.mess.852050.csv', row.names = F)
  3132. write.csv(Apal.mess.852100, 'Apal.mess.852100.csv', row.names = F)
  3133. ############################## CNAT PRES ENM ###########
  3134. ##### Loading in the Data --------------------------------------------------------------------------------------------------
  3135. # master background file;
  3136. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/CNAT/masked/Master_files_cnat_add_mask")
  3137. All.back <- read.csv('masterall.background.csv', header=T)
  3138. #filter to time period background
  3139. pres.back <- All.back %>% filter(time.bin== c('Present'))
  3140. Holo.back <- All.back %>% filter(time.bin=='Holocene')
  3141. RCP452050.back <- All.back %>% filter(time.bin=='RCP452050')
  3142. RCP852050.back <- All.back %>% filter(time.bin=='RCP852050')
  3143. RCP452100.back <- All.back %>% filter(time.bin=='RCP452100')
  3144. RCP852100.back <- All.back %>% filter(time.bin=='RCP852100')
  3145. #save background I am using
  3146. write.csv(pres.back, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/CNAT/masked/models_Cnat_pres_add_mask/pres_back.csv", row.names=FALSE)
  3147. # master occurrence file;
  3148. all.occ <- read.csv('masterall.occs.csv', header=T)
  3149. #reading in specific time period files
  3150. pres.occs <- read.csv('masterpres.occs.csv', header=T)
  3151. #check if background and occurance have same column names
  3152. identical(colnames(pres.back), colnames(pres.occs))
  3153. ##### Setting up the models ------------------------------------------------------------------------------------------------
  3154. # working directory for models
  3155. setwd("/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/CNAT/masked/models_Cnat_pres_add_mask")
  3156. # create null df - empty dataframe that null data will go into later
  3157. pres.null <- create.null.df('Cnatans', 'Present', 'Caribbean') #function(taxon.name, time.bin, extent){
  3158. # create summary df
  3159. pres.summary <- create.summary.df('Cnatans', 'Present', 'Caribbean')
  3160. create.folders.for.maxent(pres.summary)
  3161. # run null model
  3162. Cnat.null <- null.aic(null.df = pres.null,
  3163. occs = pres.occs,
  3164. background = pres.back,
  3165. first.occ.col = 10)
  3166. ##### Optimizing Model Parameters ------------------------------------------------------------------------------------------
  3167. # find most optimized model
  3168. Cnat.optim <- optimize.maxent.likelihood(pres.summary, # name of the output summary file
  3169. occs = pres.occs, # species occurrences
  3170. background = pres.back, # background for the pres
  3171. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  3172. first.occ.col = 10)
  3173. View(Cnat.optim)
  3174. #want model to be at least more than 2 AICc lower than the null
  3175. #also plan to check pROC and response curves to pick best model
  3176. write.csv(Cnat.optim, "/Users/clairewilliams/Library/CloudStorage/Box-Box/Grad_school/ENM/Jone_code/CNAT/masked/models_Cnat_pres_add_mask/Cnat_optim.csv", row.names=FALSE)
  3177. ### CHECK RESPONSE CURVES FOR REALISM!!!!!
  3178. ##### Running Cross-Validation ---------------------------------------------------------------------------------------------
  3179. ### LQP 0.1
  3180. # create eval object
  3181. # default f.class = LQP, so if f.class argument is missing, will assume LQP; only need it there in case NOT LQP
  3182. Cnatpres.eval_LQP0.1 <- create.eval.df('Cnat', 'Present', 'Caribbean', beta.values = 0.1, f.class = 'LQP')
  3183. Cnatpres.eval_LQP0.1
  3184. # create folders for Baculites in the Cenomanian
  3185. create.folders.for.maxent(Cnatpres.eval_LQP0.1)
  3186. # run eval object
  3187. Cnatpres.eval_LQP0.1 <- maxent.crossval.error(eval.df = Cnatpres.eval_LQP0.1,
  3188. occs = pres.occs, # species occurrences
  3189. background = pres.back, # background for the pres
  3190. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  3191. first.occ.col = 10,
  3192. first.test.col = 16,
  3193. omission.rate = 0, #express as proportion
  3194. all.background = All.back)
  3195. #these results go into the folders that are only 4 of the 5 abcde (ex abcd, acde etc.)
  3196. # response curves good, not all are complete humps
  3197. ### LQP 0.025
  3198. Cnatpres.eval_LQP0.025 <- create.eval.df('Cnat', 'Present', 'Caribbean', beta.values = 0.025, f.class = 'LQP')
  3199. Cnatpres.eval_LQP0.025
  3200. # create folders
  3201. create.folders.for.maxent(Cnatpres.eval_LQP0.025)
  3202. # run eval object
  3203. Cnatpres.eval_LQP0.025 <- maxent.crossval.error(eval.df = Cnatpres.eval_LQP0.025,
  3204. occs = pres.occs, # species occurrences
  3205. background = pres.back, # background for the pres
  3206. predic = 6:9, # column numbers of the predictor variables (maxsalinity, maxtemp, rangesalinity, rangetemp)
  3207. first.occ.col = 10,
  3208. first.test.col = 16,
  3209. omission.rate = 0, #express as proportion
  3210. all.background = All.back)
  3211. #response curves better but quite similar, more clear humps
  3212. ### analyzing summary files
  3213. ## if running multiple eval models, check for:
  3214. # 1.) does one model setting have systematically higher omission rates?
  3215. # 2.) do the lambdas of one model change a lot more between cross-validation reps than another model type?
  3216. # 3.) do the response curves of one model look non-sensical? check all 5 cross-validation reps
  3217. Cnatpres.eval_LQP0.1$summary # pROC 1.477102
  3218. Cnatpres.eval_LQP0.025$summary # pROC 1.446531
  3219. # going with LQP0.025 because response curves are better
  3220. ##### Evaluate Model, Calculate Threshold and Model Variability ------------------------------------------------------------
  3221. ### LQP 0.025
  3222. # evaluate model to calculate weighted suitibility and stdev
  3223. Cnatpres.means_LQP0.025 <- maxent.eval(eval = Cnatpres.eval_LQ

COBI-40-e70323-s014.R, no license · at the source

Overview

  1. Department of Earth and Planetary Sciences, The University of Texas at Austin, Austin, Texas, USA
  2. Department of Biology, The University of New Mexico, Albuquerque, New Mexico, USA
  3. Department of Earth and Planetary Sciences, The University of New Mexico, Albuquerque, New Mexico, USA
Institutions: The University of Texas at Austin (United States); University of New Mexico (United States)
Dates: received 1 June 2025; accepted 16 March 2026; published online 13 May 2026; in print October 2026
Type: Research article · Language: English
License: CC BY-NC
Identifiers: DOI 10.1111/cobi.70323 · PMID 42125997 · PMCID PMC13613574 · OpenAlex W7161027982
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: none (in silico) (organism), computational (subfield)
Methods: Statistics, Smoothing, state filtering, decompositions, Machine learning
Keywords: Acropora, Caribbean, Colpophyllia, coral reef, Holocene, palaeoecological niche models, Porites, arrecife de coral, Caribe, Holoceno, modelos de nicho paleoecológico, 古生态位模型, 加勒比海, 全新世, 珊瑚礁, 鹿角珊瑚(Acropora), 滨珊瑚(Porites), 有沟珊瑚(Colpophyllia)
MeSH: Anthozoa*, Climate Change*, Conservation of Natural Resources*, Coral Reefs*, Ecosystem*, Fossils*, Models, Biological*, Animals, Caribbean Region, Models, Theoretical (* major topic)
Topic: Species Distribution and Climate Change (Ecological Modeling, Environmental Science), according to OpenAlex
Funding: NIH HHS (DGE 2137420); National Science Foundation (DGE-2137420, DGE‐2137420)
Citations: cited by 1 paper (Europe PMC); 137 references in the paper

Abstract

Ecological niche models (ENMs) are used to assess the abiotic preferences of species by linking their occurrences to the environmental conditions in which they live. We developed a fossil‐informed ENM framework that integrates mid‐Holocene and modern occurrences to test niche stability and reconstruct abiotic niche characteristics for four critical reef‐building Caribbean coral species (elkhorn coral [Acropora palmata], staghorn coral [Acropora cervicornis], boulder brain coral [Colpophyllia natans], and mustard hill coral [Porites astreoides]). Given evidence of niche stability, we used fossil‐improved niche estimates to predict area and location of habitat for future climate scenarios in 2050 and 2100. We built species distribution models with environmental predictors and compared models trained with modern‐only versus combined fossil and modern occurrences to evaluate differences in niche breadth, model performance, and projected habitat distributions under future climate scenarios. Including mid‐Holocene fossil data in ENMs broadened niche estimates, resulting in a larger area of predicted habitat than models based solely on modern data (up to 114,559 km2 more in 2100). Although our models showed that suitable habitats existed for most corals in 2100, the amount declined dramatically (45–100% decrease in area from the present day), there was a significant restriction of lower latitude habitat suitability, and marine protected areas did not overlap the majority of predicted future suitable habitat (8–20% overlap by 2100). Fossil‐informed models expanded niche estimates in environmental space and incorporated environmental conditions not represented in modern data, resulting in broader projections of future habitat. Our results suggest that actions to reduce emissions and expand protected areas in the northern Caribbean are imperative to prevent significant degradation and that using fossil occurrences in niche estimation can improve the reliability of conservation forecasting, an approach that is transferable across taxa and regions.

Reproduced under the paper's license (CC BY-NC), from the paper cited above.

Repository

Its files are read in the Code ↔ Paper reader above, with 2 matches between paragraphs and lines of code.

supp:PMC13613574/COBI-40-e70323-s014.R

License: none: the authors keep all their rights
State: the link answers, verified on 28 September 2026
Evidence: files inventoried
Languages: R (1)
Size: 1 file, 1 script
Software Heritage: not checked
Found in: the supplementary material
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: ggplot2 (1 file), tidyverse (1 file)
Availability: 1 check, the latest on 28 September 2026: the link answers (HTTP 200)
  • 28 September 2026: the link answers (HTTP 200)
1 file

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 1 script, each with its path and the digest of its content;
  • 2 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 2, 28 September 2026

  • Publisher: n/a → Wiley

Version 1, 28 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 4 authors, 18 keywords, 10 MeSH terms, 2 funders, 119 references.

Cite

This paper

Williams, C. M., Machado‐Stredel, F., Martindale, R. C., & Myers, C. E. (2026). Integrating fossil data in ecological niche models to improve predictions of future habitat of Caribbean corals. Conservation biology : the journal of the Society for Conservation Biology, 40(5), e70323. https://doi.org/10.1111/cobi.70323

BibTeX

@article{williams2026integrating,
author = {Williams, Claire M and Machado‐Stredel, Fernando and Martindale, Rowan C and Myers, Corinne E},
title = {{Integrating fossil data in ecological niche models to improve predictions of future habitat of Caribbean corals}},
journal = {Conservation biology : the journal of the Society for Conservation Biology},
year = {2026},
month = may,
volume = {40},
number = {5},
pages = {e70323},
publisher = {Wiley},
issn = {1523-1739},
doi = {10.1111/cobi.70323},
url = {https://doi.org/10.1111/cobi.70323},
pmid = {42125997},
pmcid = {PMC13613574}
}

RIS

TY - JOUR
AU - Williams, Claire M
AU - Machado‐Stredel, Fernando
AU - Martindale, Rowan C
AU - Myers, Corinne E
TI - Integrating fossil data in ecological niche models to improve predictions of future habitat of Caribbean corals
T2 - Conservation biology : the journal of the Society for Conservation Biology
J2 - Conserv Biol
PY - 2026
DA - 2026/05/13
VL - 40
IS - 5
SP - e70323
SN - 1523-1739
PB - Wiley
DO - 10.1111/cobi.70323
UR - https://doi.org/10.1111/cobi.70323
LA - en
ER -

CSL-JSON

{
"id": "10.1111/cobi.70323",
"type": "article-journal",
"title": "Integrating fossil data in ecological niche models to improve predictions of future habitat of Caribbean corals",
"container-title": "Conservation biology : the journal of the Society for Conservation Biology",
"author": [
{
"family": "Williams",
"given": "Claire M"
},
{
"family": "Machado‐Stredel",
"given": "Fernando"
},
{
"family": "Martindale",
"given": "Rowan C"
},
{
"family": "Myers",
"given": "Corinne E"
}
],
"container-title-short": "Conserv Biol",
"volume": "40",
"issue": "5",
"page": "e70323",
"DOI": "10.1111/cobi.70323",
"PMID": "42125997",
"PMCID": "PMC13613574",
"ISSN": "1523-1739",
"publisher": "Wiley",
"URL": "https://doi.org/10.1111/cobi.70323",
"language": "en",
"issued": {
"date-parts": [
[
2026,
5,
13
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1111/gcb.70818 [code]
Persistent Legacy Effects of Marine Heatwaves on Coral Symbioses.
Journal: Global change biology
In common: ggplot2, tidyverse, 1 reference
[2] doi:10.1093/nc/niag029 [code]
A data-driven approach to identifying and evaluating connectivity-based neural correlates of conscious visual perception.
Journal: Neuroscience of consciousness
In common: ggplot2, tidyverse, none (in silico)
[3] doi:10.1038/s44220-026-00669-7 [code]
Deviations in effective connectivity explain different hallucination subtypes in Parkinson's disease psychosis.
Journal: Nature. Mental health
In common: ggplot2, tidyverse, computational
[4] doi:10.1002/hbm.70546 [code]
ComBat-Predict Enhances Generalizability of Neuroimaging Models to New Sites.
Journal: Human brain mapping
In common: ggplot2, tidyverse, computational
[5] doi:10.1038/s41467-026-69853-8 [code]
Transcranial focused ultrasound induces source localizable cortical activation in resting state humans when applied concurrently with transcranial electric stimulation.
Journal: Nature communications
In common: ggplot2, tidyverse, computational
[6] doi: [code]
Going deeper with morphologically detailed neural networks by simulation-based gradient propagation
Journal: Frontiers in computational neuroscience
In common: none (in silico), computational
[7] doi:10.1007/s00422-026-01063-3 [code]
Increased firing rates monotonically expand neuronal coding bandwidth.
Journal: Biological cybernetics
In common: none (in silico), computational
[8] doi:10.1371/journal.pcbi.1014617 [code]
An in silico framework for dissecting the mechanistic origins of in vivo recorded neuronal activity.
Journal: PLoS computational biology
In common: none (in silico), computational
[9] doi:10.1007/s00422-026-01048-2 [code]
A quality measure for repeating multiple-unit spike patterns.
Journal: Biological cybernetics
In common: none (in silico), computational
[10] doi:10.1007/s11571-026-10522-3 [code]
Acetylcholine enhances deviance detection in Hodgkin-Huxley neuronal networks.
Journal: Cognitive neurodynamics
In common: none (in silico), computational

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.