minorFuns.R 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. #' Minor MODIS Package Functions
  2. #'
  3. #' @description
  4. #' Compendium of minor \strong{MODIS} package-related functions.
  5. #'
  6. #' @param pattern Regular expression passed to \code{\link{grep}}.
  7. #' @param database \code{character}. Defaults to \code{"worldHires"}, see
  8. #' \code{\link{map}} for available options.
  9. #' @param plot \code{logical}, defaults to \code{FALSE}. If \code{TRUE}, search
  10. #' results are displayed.
  11. #'
  12. #' @return
  13. #' A \code{list} of length 2. The first entry is the call to create the given
  14. #' map, whereas the second entry represents the names of areas within the
  15. #' search.
  16. #'
  17. #' @author
  18. #' Matteo Mattiuzzi
  19. #'
  20. #' @seealso
  21. #' \code{\link{getTile}}, \code{\link{map}}, \code{\link{grep}}.
  22. #'
  23. #' @examples
  24. #' \dontrun{
  25. #' search4map()
  26. #'
  27. #' search4map(pattern="USA",plot=TRUE)
  28. #' search4map(database="state",plot=TRUE)?map
  29. #'
  30. #' search4map(database="italy",pattern="Bolz",plot=TRUE)
  31. #'
  32. #' search4map(pattern="Sicily",plot=TRUE)
  33. #' }
  34. #'
  35. #' @name minorFuns
  36. NULL
  37. ##########################################
  38. # central setting for stubbornness
  39. stubborn <- function(level = "high") {
  40. ## supported 'character' levels
  41. levels <- c("low", "medium", "high", "veryhigh", "extreme")
  42. ## if stubbornness is a 'character', try to find it in 'levels' or convert it
  43. ## to regular 'numeric'
  44. if (!is.numeric(level) & !tolower(level) %in% levels) {
  45. level <- suppressWarnings(try(as.numeric(level), silent = TRUE))
  46. if (inherits(level, "try-error") | is.na(level))
  47. stop("Unrecognised 'stubbornness' level!")
  48. }
  49. ## round or convert 'character' level to 'numeric'
  50. if (is.numeric(level)) {
  51. round(level)
  52. } else {
  53. c(5, 15, 50, 100, 1000)[which(tolower(level) == levels)]
  54. }
  55. }
  56. checksizefun <- function(file,sizeInfo=NULL,flexB=0)
  57. {
  58. # determine reference size
  59. if (is.null(sizeInfo))
  60. {
  61. xmlfile <- paste0(file,".xml")
  62. xmlfile <- xmlParse(xmlfile)
  63. MetaSize <- getNodeSet(xmlfile, "/GranuleMetaDataFile/GranuleURMetaData/DataFiles/DataFileContainer/FileSize" )
  64. MetaSize <- as.numeric(xmlValue(MetaSize[[1]])) # expected filesize
  65. } else
  66. {
  67. MetaSize <- as.numeric(sizeInfo[which(sizeInfo[,1]==basename(file)),2])
  68. }
  69. if(length(MetaSize)==0)
  70. {
  71. res <- list(MetaSize=NULL,FileSize=NULL,isOK=NULL)
  72. return(res)
  73. }
  74. FileSize <- as.numeric(fileSize(file))
  75. if (flexB!=0)
  76. {
  77. isOK <- (MetaSize >= FileSize-flexB & MetaSize <= FileSize+flexB)
  78. } else
  79. {
  80. isOK <- (MetaSize == FileSize)
  81. }
  82. res <- list(MetaSize=MetaSize,FileSize=FileSize,isOK=as.logical(isOK))
  83. return(res)
  84. }
  85. #' @describeIn minorFuns Simplifies search for \strong{mapdata}-based extents
  86. #' @aliases search4map
  87. #' @export search4map
  88. search4map <- function(pattern="",database='worldHires',plot=FALSE)
  89. {
  90. areas <- grep(x=maps::map(database,plot=FALSE)$names,pattern=pattern,value=TRUE,ignore.case=TRUE)
  91. if (length(areas)==0)
  92. {
  93. cat("No country (region or island) found! please change your pattern!\n")
  94. return(invisible(NULL))
  95. } else
  96. {
  97. if (plot)
  98. {
  99. maps::map(database,areas)
  100. map.axes()
  101. box()
  102. grid(36,18,col="blue",lwd=0.5)
  103. if(length(areas)>4)
  104. {
  105. subareas <- paste(areas[1:3],collapse=", ")
  106. title(c(paste(subareas,"and",(length(areas)-3),"other")))
  107. } else
  108. {
  109. title(areas)
  110. }
  111. }
  112. return(areas=areas)
  113. }
  114. }
  115. checkTools <- function(tool=c("MRT","GDAL"), quiet=FALSE, opts = NULL)
  116. {
  117. tool <- toupper(tool)
  118. iw <- options()$warn
  119. options(warn=-1)
  120. on.exit(options(warn=iw))
  121. MRT <- NULL
  122. GDAL <- NULL
  123. if ("MRT" %in% tool)
  124. {
  125. MRT <- FALSE
  126. mrtH <- normalizePath(Sys.getenv("MRT_HOME"), winslash="/", mustWork = FALSE)
  127. mrtDD <- normalizePath(Sys.getenv("MRT_DATA_DIR"), winslash="/", mustWork = FALSE)
  128. if (!quiet)
  129. {
  130. cat("Checking availability of MRT:\n")
  131. }
  132. if(mrtH=="")
  133. {
  134. cat(" 'MRT_HOME' not set/found! MRT is NOT enabled! See: 'https://lpdaac.usgs.gov/tools/modis_reprojection_tool'\n")
  135. } else
  136. {
  137. if (!quiet)
  138. {
  139. cat(" 'MRT_HOME' found:", mrtH,"\n")
  140. }
  141. if (mrtDD=="")
  142. {
  143. cat(" 'MRT_DATA_DIR' not set/found! MRT is NOT enabled! You need to set the path, read in the MRT manual! 'https://lpdaac.usgs.gov/tools/modis_reprojection_tool'\n")
  144. } else
  145. {
  146. if (!quiet)
  147. {
  148. cat(" 'MRT_DATA_DIR' found:",mrtDD,"\n")
  149. cat(" MRT enabled, settings are fine!\n")
  150. }
  151. MRT <- TRUE
  152. }
  153. }
  154. if(MRT)
  155. {
  156. if(file.exists(paste0(mrtH,"/doc/ReleaseNotes.txt")))
  157. {
  158. x <- file(paste0(mrtH,"/doc/ReleaseNotes.txt"),open="rt")
  159. v <- readLines(x)
  160. v <- v[(grep(v,pattern="------*")-1)]
  161. v <- v[grep(v,pattern="Version ")][1]
  162. close(x)
  163. } else
  164. {
  165. v <- "Enabled"
  166. }
  167. } else
  168. {
  169. v <- "Version not determined"
  170. }
  171. MRT <- list(MRT=MRT,version=v)
  172. }
  173. if ("GDAL" %in% tool)
  174. {
  175. GDAL <- FALSE
  176. gdv <- NA
  177. if (is.null(opts))
  178. opts <- combineOptions(checkTools = FALSE)
  179. if (.Platform$OS=="unix")
  180. {
  181. if (!quiet)
  182. {
  183. cat("Checking availability of GDAL:\n")
  184. }
  185. cmd <- paste0(opts$gdalPath,'gdalinfo --version')
  186. gdaltext <- try(system(cmd,intern=TRUE),silent=TRUE)
  187. if (inherits(gdaltext,"try-error"))
  188. {
  189. cat(" GDAL not found, install 'gdal-bin' or check path settings in order to use related functionalities (see '?MODISoptions')!\n")
  190. gdaltext <- "Could not determine GDAL version!"
  191. } else
  192. {
  193. if (!quiet)
  194. {
  195. cat(" OK,",gdaltext,"found!\n")
  196. }
  197. GDAL <- TRUE
  198. gdv <- strsplit(gdaltext,",")[[1]][1]
  199. gdv <- raster::trim(gsub(gdv,pattern="GDAL",replacement=""))
  200. gdv <- as.numeric(strsplit(gdv,"\\.")[[1]])
  201. }
  202. GDAL <- list(GDAL=GDAL,version=gdaltext,vercheck=gdv)
  203. } else
  204. {
  205. if (!quiet)
  206. {
  207. cat("Checking availability of 'FWTools/OSGeo4W' (GDAL with HDF4 support for Windows):\n")
  208. }
  209. cmd <- paste0(opts$gdalPath,'gdalinfo --version')
  210. gdaltext <- shell(cmd,intern=TRUE)
  211. if (length(grep(x=gdaltext,pattern="GDAL",ignore.case = TRUE))==0)
  212. {
  213. cat("'FWTools/OSGeo4W' installation not found or path not set.\nIf you don't have installed one of them you can get it from 'http://fwtools.maptools.org/' or 'http://trac.osgeo.org/osgeo4w/' (recommanded)\nTrying to autodetect path to 'FWTools/OSGeo4W' (this may takes some time, you can interupt this process and set it manually, see 'gdalPath' argument in '?MODISoptions':\n\n")
  214. a <- dirname(list.files(path="c:/",pattern="^gdalinfo.exe$", full.names=TRUE, recursive=TRUE,include.dirs=TRUE))
  215. if (length(a)==0)
  216. {
  217. stop("No 'FWTools/OSGeo4W' installation(s) found! In order to use related function please solve this problem first.\n")
  218. }
  219. fwt <- a[grep(a,pattern="FWTools",ignore.case = TRUE)]
  220. osg <- a[grep(a,pattern="OSGeo4W",ignore.case = TRUE)]
  221. minone <- FALSE
  222. if(length(fwt)==1)
  223. {
  224. fwtP <- shQuote(utils::shortPathName(normalizePath(paste0(fwt,"/gdalinfo.exe"),winslash="/")))
  225. fwtV <- shell(paste0(fwtP, " --version"),intern=TRUE)
  226. fwtV <- strsplit(strsplit(fwtV,",")[[1]][1]," ")[[1]][2]
  227. if(checkGdalDriver(fwt))
  228. {
  229. cat("Found 'FWTools' version: '", fwtV,"' to enalbe this run:\n MODISoptions(gdalPath='",normalizePath(fwt,"/"),"')\n",sep="")
  230. minone <- TRUE
  231. } else
  232. {
  233. cat("Found 'FWTools' version: '", fwtV,"' in '",normalizePath(fwt,"/"),"' but without HDF4 support...strange, try to remove and re-install 'FWTools'!\n",sep="")
  234. }
  235. }
  236. if(length(osg)==1)
  237. {
  238. osgP <- shQuote(utils::shortPathName(normalizePath(paste0(osg,"/gdalinfo.exe"),winslash="/")))
  239. osgV <- shell(paste0(osgP, " --version"),intern=TRUE)
  240. osgV <- strsplit(strsplit(osgV,",")[[1]][1]," ")[[1]][2]
  241. if(checkGdalDriver(osg))
  242. {
  243. cat("Found 'OSgeo4W' version: '", osgV,"' to enable this run:\n MODISoptions(gdalPath='",normalizePath(osg,"/"),"')\n",sep="")
  244. minone <- TRUE
  245. } else
  246. {
  247. cat("Found 'OSgeo4W' version: '", osgV,"' in '",normalizePath(osg,"/"),"' but without HDF4 support...strange, try to remove and re-install 'OSgeo4W'!\n",sep="")
  248. }
  249. }
  250. if (!minone)
  251. {
  252. cat("No HDF4 supporting GDAL installation found. You may set it manually in MODISoptions(gdalPath='/Path/to/XXGDAL/bin')\n")
  253. }
  254. gdaltext <- "Could not determine GDAL version!"
  255. } else
  256. {
  257. if (!quiet)
  258. {
  259. cat(" OK,",gdaltext,"found!\n")
  260. }
  261. GDAL <- TRUE
  262. gdv <- strsplit(gdaltext,",")[[1]][1]
  263. gdv <- raster::trim(gsub(gdv,pattern="GDAL",replacement=""))
  264. gdv <- as.numeric(strsplit(gdv,"\\.")[[1]])
  265. }
  266. GDAL <- list(GDAL = GDAL, version = gdaltext,vercheck=gdv)
  267. }
  268. }
  269. return(invisible(list(GDAL=GDAL,MRT=MRT)))
  270. }
  271. # get gdal write formats (driver 'name', 'long name' and 'extension')
  272. gdalWriteDriver <- function(renew = FALSE, quiet = TRUE,...)
  273. {
  274. iw <- options()$warn
  275. options(warn=-1)
  276. on.exit(options(warn=iw))
  277. opt <- combineOptions(...)
  278. outfile <- paste0(opt$outDirPath,".auxiliaries/gdalOutDriver.RData")
  279. if (!is.null(getOption("MODIS_gdalOutDriver"))) # take it from options()
  280. {
  281. gdalOutDriver <- getOption("MODIS_gdalOutDriver")
  282. } else if(file.exists(outfile)) # or from RData
  283. {
  284. load(outfile)
  285. }
  286. if(exists("gdalOutDriver"))
  287. {
  288. if (nrow(gdalOutDriver)<5)
  289. {
  290. renew <- TRUE
  291. }
  292. } else
  293. {
  294. renew <- TRUE
  295. }
  296. if (renew)
  297. {
  298. if(!quiet)
  299. {
  300. message("Detecting available write drivers!")
  301. }
  302. cmd <- paste0(opt$gdalPath,"gdalinfo --formats")
  303. # list all drivers with (rw)
  304. if (.Platform$OS=="unix")
  305. {
  306. gdalOutDriver <- system(cmd,intern=TRUE)
  307. } else
  308. {
  309. gdalOutDriver <- shell(cmd,intern=TRUE)
  310. }
  311. gdalOutDriver <- grep(gdalOutDriver,pattern="\\(rw",value=TRUE) # this regex must be preciser
  312. name <- sapply(gdalOutDriver,function(x){strsplit(x,"\\(")[[1]][1]})
  313. name <- gsub(as.character(name), pattern=" ", replacement="")
  314. #tnauss
  315. name <- sapply(name, function(x){return(strsplit(x, "-")[[1]][1])})
  316. description <- as.character(sapply(gdalOutDriver,function(x){strsplit(x,"\\): ")[[1]][2]}))
  317. if(!quiet)
  318. {
  319. message("Found: ",length(name)," candidate drivers, detecting file extensions...")
  320. }
  321. extension <- rep(NA,length(name))
  322. for (i in seq_along(name))
  323. {
  324. ind <- grep(name, pattern=paste0("^",name[i],"$"), ignore.case=TRUE, value=FALSE)
  325. if (length(ind)!=0)
  326. {
  327. extension[i] <- getExtension(name[ind],gdalPath = opt$gdalPath)
  328. }
  329. }
  330. if(!quiet)
  331. {
  332. message(sum(!is.na(extension))," usable drivers detected!")
  333. }
  334. gdalOutDriver <- data.frame(name=name[!is.na(extension)], description=description[!is.na(extension)], extension=extension[!is.na(extension)], stringsAsFactors=FALSE)
  335. if(!file.exists(opt$outDirPath))
  336. {
  337. opt$outDirPath <- setPath(opt$outDirPath,ask = FALSE)
  338. opt$auxPath <- setPath(paste0(opt$outDirPath,".auxiliaries"),ask=FALSE)
  339. }
  340. if (dir.exists(opt$auxPath))
  341. {
  342. save(gdalOutDriver, file=outfile)
  343. }
  344. }
  345. gdalOutDriver
  346. }
  347. getExtension <- function(dataFormat,...)
  348. {
  349. if(toupper(dataFormat) %in% c("HDF-EOS","HDF4IMAGE")) # MRT + GDAL
  350. {
  351. return(".hdf")
  352. } else if (toupper(dataFormat) %in% c("GTIFF","GEOTIFF")) # MRT + GDAL
  353. {
  354. return(".tif")
  355. } else if (tolower(dataFormat) =="raw binary") # MRT + GDAL
  356. {
  357. return(".hdr")
  358. } else if (toupper(dataFormat)=="ENVI")
  359. {
  360. return("") # should generate a '.hdr' file + a file without extension
  361. } else if (dataFormat=="FIT")
  362. {
  363. return(NA)
  364. } else if (toupper(dataFormat)=="ILWIS")
  365. {
  366. return(".mpr") # is this ok?
  367. } else
  368. {
  369. gdalPath <- combineOptions(...)$gdalPath
  370. cmd <- paste0(gdalPath,'gdalinfo --format ')
  371. if(.Platform$OS.type=="unix")
  372. {
  373. ext <- system(paste0(cmd, dataFormat),intern=TRUE)
  374. } else
  375. {
  376. ext <- shell(paste0(cmd, dataFormat),intern=TRUE)
  377. }
  378. ext <- grep(ext,pattern="Extension:",value=TRUE)
  379. if(length(ext)==0)
  380. {
  381. return(NA)
  382. } else
  383. {
  384. ext <- gsub(strsplit(ext,":")[[1]][2],pattern=" ",replacement="")
  385. if (ext!="")
  386. {
  387. ext <- paste0(".",ext)
  388. }
  389. return(ext)
  390. }
  391. }
  392. }
  393. isSupported <- function(x)
  394. {
  395. fname <- basename(x)
  396. iw <- options()$warn
  397. options(warn=-1)
  398. on.exit(options(warn=iw))
  399. res <- sapply(fname,function(y)
  400. {
  401. product <- getProduct(y,quiet=TRUE)
  402. if (is.null(product))
  403. {
  404. return(FALSE)
  405. } else
  406. {
  407. secName <- defineName(product$request)
  408. if (product$SENSOR[1] == "MODIS")
  409. {
  410. if (product$TYPE[1] == "Tile")
  411. {
  412. Tpat <- "h[0-3][0-9]v[0-1][0-9]" # to enhance
  413. return(all((grep(secName["TILE"],pattern=Tpat)) + (substr(secName["DATE"],1,1) == "A") + (length(secName)==6)))
  414. } else if (product$TYPE[1] == "CMG")
  415. {
  416. return(all((substr(secName["DATE"],1,1) == "A") + (length(secName)==5)))
  417. } else if (product$TYPE[1] == "Swath") # actually no support for Swath data!
  418. {
  419. # return(all((substr(secName["DATE"],1,1) == "A") + (length(secName)==6)))
  420. # } else {
  421. return(FALSE)
  422. }
  423. } else
  424. {
  425. return(FALSE)
  426. }
  427. }
  428. })
  429. return(unlist(res))
  430. }
  431. # TODO enhancement of SENSOR/PRODUCT detection capabilities!
  432. # the methods below are based on the results of strsplit().
  433. defineName <- function(x) # "x" is a MODIS or filename
  434. {
  435. if(missing(x))
  436. {
  437. stop("Error in function 'defineName', x is missing, must be a MODIS filename!")
  438. } else
  439. {
  440. fname <- basename(x)
  441. secName <- strsplit(fname,"\\.")[[1]] # for splitting with more signes "[._-]"
  442. sensor="MODIS"
  443. ###################################
  444. # NAME definitions (is File-specific!)
  445. #########################
  446. # MODIS
  447. if (sensor=="MODIS")
  448. {
  449. product <- getProduct(x=secName[1],quiet=TRUE)
  450. if (product$TYPE=="Tile")
  451. {
  452. names(secName) <- c("PRODUCT","DATE","TILE","CCC","PROCESSINGDATE","FORMAT")
  453. } else if (product$TYPE=="CMG")
  454. {
  455. names(secName) <- c("PRODUCT","DATE","CCC","PROCESSINGDATE","FORMAT")
  456. } else if (product$TYPE=="Swath")
  457. {
  458. names(secName) <- c("PRODUCT","DATE","TIME","CCC","PROCESSINGDATE","FORMAT")
  459. } else
  460. {
  461. stop("Not a MODIS 'Tile', 'CMG' or 'Swath'!")
  462. }
  463. } # XXX else if .... add Products here
  464. }
  465. return(secName)
  466. }
  467. # this function selects elements of a list by "row".
  468. listPather <- function(x,index)
  469. {
  470. x <- as.list(x)
  471. res <- list()
  472. for (i in seq_along(x))
  473. {
  474. res[[i]] <- x[[i]][index]
  475. }
  476. names(res) <- names(x)
  477. return(res)
  478. }
  479. # list files in a Url
  480. filesUrl <- function(url)
  481. {
  482. if (substr(url,nchar(url),nchar(url))!="/")
  483. {
  484. url <- paste0(url,"/")
  485. }
  486. iw <- options()$warn
  487. options(warn=-1)
  488. on.exit(options(warn=iw))
  489. ## default method (e.g. LPDAAC, LAADS)
  490. if (length(grep("ntsg", url)) == 0) {
  491. co <- try(RCurl::getURL(url, ftp.use.epsv = FALSE), silent = TRUE)
  492. if (inherits(co, "try-error")) return(FALSE)
  493. if (substring(url,1,4)=="http")
  494. {
  495. co <- XML::htmlTreeParse(co)
  496. co <- co$children[[1]][[2]][[2]]
  497. co <- sapply(co$children, function(el) XML::xmlGetAttr(el, "href"))
  498. co <- as.character(unlist(co))
  499. co <- co[!co %in% c("?C=N;O=D", "?C=M;O=A", "?C=S;O=A", "?C=D;O=A")]
  500. fnames <- co[-1]
  501. } else
  502. {
  503. co <- strsplit(co, if(.Platform$OS.type=="unix"){"\n"} else{"\r\n"})[[1]]
  504. co <- strsplit(co," ")
  505. elim <- grep(co,pattern="total")
  506. if(length(elim)==1)
  507. {
  508. co <- co[-elim]
  509. }
  510. fnames <- basename(sapply(co,function(x){x[length(x)]}))
  511. }
  512. ## NTSG method; if not used, connection breakdowns are likely to occur
  513. } else {
  514. # 'MODIS' options
  515. opts <- combineOptions()
  516. # download website to opts$auxPath
  517. file_out <- paste0(opts$auxPath, "/index.html")
  518. jnk <- capture.output(
  519. download.file(url = url, destfile = file_out, quiet = TRUE, method = "wget")
  520. )
  521. # extract information from website content
  522. content <- readLines(file_out)
  523. fnames <- sapply(
  524. strsplit(
  525. sapply(
  526. lapply(strsplit(content, "<a href=")[[1]], function(i) {
  527. strsplit(i, "</a>")[[1]]
  528. }),
  529. "[[", 1),
  530. ">"),
  531. "[[", 2)
  532. fnames <- fnames[grep("^MOD16.*MERRAGMAO$|^Y2|^D|^MOD16.*hdf$", fnames)]
  533. fnames <- gsub("_MERRAGMAO", "", fnames)
  534. # remove temporary file and return output
  535. invisible(file.remove(file_out))
  536. }
  537. ## format and return
  538. fnames <- gsub(fnames,pattern="/",replacement="")
  539. return(fnames)
  540. }
  541. #http://ryouready.wordpress.com/2008/12/18/generate-random-string-name/
  542. makeRandomString <- function(n=1, length=12)
  543. {
  544. randomString <- c(1:n) # initialize vector
  545. for (i in 1:n)
  546. {
  547. randomString[i] <- paste0(sample(c(0:9, letters, LETTERS),
  548. length, replace=TRUE),collapse="")
  549. }
  550. return(randomString)
  551. }
  552. # this function care about the download of files. Based on remotePath (result of genString) it alterates the effort on available sources and stops after succeded download or by reacing the stubbornness thresshold.
  553. ModisFileDownloader <- function(x, opts = NULL, ...)
  554. {
  555. x <- basename(x)
  556. ## if options have not been passed down, create them from '...'
  557. if (is.null(opts))
  558. opts <- combineOptions(...)
  559. opts$stubbornness <- stubborn(opts$stubbornness)
  560. opts$quiet <- as.logical(opts$quiet)
  561. iw <- options()$warn
  562. options(warn=-1)
  563. on.exit(options(warn=iw))
  564. out <- rep(NA,length=length(x))
  565. for (a in seq_along(x))
  566. { # a=1
  567. path <- genString(x[a], opts = opts)
  568. path$localPath <- setPath(path$localPath)
  569. hv <- seq_along(opts$MODISserverOrder)
  570. hv <- rep(hv,length=opts$stubbornness)
  571. g=1
  572. while(g <= opts$stubbornness)
  573. {
  574. if (!opts$quiet)
  575. {
  576. cat("\nGetting file from:",opts$MODISserverOrder[hv[g]],"\n############################\n")
  577. }
  578. destfile <- paste0(path$localPath,x[a])
  579. if(!.Platform$OS=="windows" & opts$dlmethod=="aria2")
  580. {
  581. out[a] <- system(paste0("aria2c -x 3 --file-allocation=none ",paste(path$remotePath[which(names(path$remotePath)==opts$MODISserverOrder[hv[g]])],x[a],sep="/",collapse="")," -d ", dirname(destfile)))
  582. } else
  583. {
  584. ## if server is 'LPDAAC' or 'LAADS', consider MODISserverOrder
  585. if (any(names(path$remotePath) %in% opts$MODISserverOrder[hv[g]])) {
  586. id_remotepath <- which(names(path$remotePath) == opts$MODISserverOrder[hv[g]])
  587. ## if not (e.g. when server is 'NTSG'), simply take the first `path$remotePath` entry
  588. } else {
  589. id_remotepath <- 1
  590. }
  591. server <- names(path$remotePath)
  592. if (length(server) > 1)
  593. server <- server[which(server %in% opts$MODISserverOrder[hv[g]])]
  594. infile <- paste(path$remotePath[id_remotepath], x[a], sep = "/",
  595. collapse = "")
  596. ## adapt 'dlmethod' and 'extra' if server == "LPDAAC"
  597. if (server == "LPDAAC") {
  598. if (!opts$dlmethod %in% c("wget", "curl")) {
  599. warning("Data download from '", server,
  600. "' is currently only available through wget and curl.\n",
  601. "Setting MODISoptions(dlmethod = 'wget') ",
  602. "(or run MODISoptions(dlmethod = 'curl') to use curl instead) ...\n")
  603. method <- "wget"
  604. } else {
  605. method <- opts$dlmethod
  606. }
  607. # wget extras
  608. ofl = path.expand("~/.cookies.txt")
  609. if (!file.exists(ofl))
  610. jnk = file.create(ofl)
  611. extra <- if (method == "wget") {
  612. paste("--load-cookies", ofl
  613. , "--save-cookies", ofl
  614. , "--keep-session-cookie --no-check-certificate")
  615. # curl extras
  616. } else {
  617. paste('-n -L -c', ofl, '-b', ofl)
  618. }
  619. ## else if server == "NTSG", choose 'wget' as download method
  620. } else if (server == "NTSG") {
  621. method <- "wget"
  622. extra <- getOption("download.file.extra")
  623. ## else use default settings
  624. } else {
  625. method <- opts$dlmethod
  626. extra <- getOption("download.file.extra")
  627. }
  628. out[a] <- try(
  629. download.file(url = infile, destfile = destfile, mode = 'wb',
  630. method = method, quiet = opts$quiet,
  631. cacheOK = FALSE, extra = extra),
  632. silent = TRUE)
  633. }
  634. if (is.na(out[a])) {cat("File not found!\n"); unlink(destfile); break} # if NA then the url name is wrong!
  635. if (out[a]!=0 & !opts$quiet) {cat("Remote connection failed! Re-try:",g,"\r")}
  636. if (out[a]==0 & !opts$quiet & g>1) {cat("Downloaded after:",g,"re-tries\n\n")}
  637. if (out[a]==0 & !opts$quiet & g==1) {cat("Downloaded by the first try!\n\n")}
  638. if (out[a]==0) {break}
  639. Sys.sleep(opts$wait)
  640. g=g+1
  641. }
  642. }
  643. return(!as.logical(out))
  644. }
  645. doCheckIntegrity <- function(x, opts = NULL, ...) {
  646. x <- basename(x)
  647. ## if options have not been passed down, create them from '...'
  648. if (is.null(opts))
  649. opts <- combineOptions(...)
  650. opts$stubbornness <- stubborn(opts$stubbornness)
  651. out <- rep(NA,length=length(x))
  652. for (a in seq_along(x))
  653. {
  654. if(basename(x[a])=="NA")
  655. {
  656. out[a] <- NA
  657. } else
  658. {
  659. path <- genString(x[a], opts = opts)
  660. path$localPath <- setPath(path$localPath)
  661. hv <- 1:length(path$remotePath)
  662. hv <- rep(hv,length=opts$stubbornness)
  663. g=1
  664. while(g <= opts$stubbornness)
  665. {
  666. if (g==1)
  667. {
  668. out[a] <- checkIntegrity(x = x[a], opts = opts)
  669. }
  670. if (is.na(out[a]))
  671. {
  672. unlink(x[a])
  673. break
  674. }
  675. if (!out[a])
  676. {
  677. if (!opts$quiet)
  678. {
  679. cat(basename(x[a]),"is corrupted, trying to re-download it!\n\n")
  680. }
  681. unlink(x[a])
  682. out[a] <- ModisFileDownloader(x[a], opts = opts)
  683. } else if (out[a])
  684. {
  685. break
  686. }
  687. out[a] <- checkIntegrity(x = x[a], opts = opts)
  688. g=g+1
  689. }
  690. }
  691. }
  692. return(as.logical(out))
  693. }
  694. # setPath for localArcPath and outDirPath
  695. setPath <- function(path, ask=FALSE, showWarnings=FALSE, mkdir = TRUE)
  696. {
  697. path <- normalizePath(path, "/", mustWork = FALSE)
  698. ## Strip any trailing slashes from the path as file.exists() returns
  699. ## FALSE for detecting folders with a trailing slash:
  700. path <- gsub("/$", "", path)
  701. if(!file.exists(path) & mkdir)
  702. {
  703. doit <- 'Y'
  704. if (ask)
  705. {
  706. doit <- toupper(readline(paste0(path," does not exist, should it be created? [y/n]: ")))
  707. }
  708. if (doit %in% c("Y","YES"))
  709. {
  710. stopifnot(dir.create(path, recursive = TRUE, showWarnings = showWarnings))
  711. } else
  712. {
  713. stop("Path not set, use ?MODISoptions to configure it")
  714. }
  715. }
  716. return(correctPath(path))
  717. }
  718. # get NA values from getSds(x)$SDS4gdal
  719. getNa <- function(x)
  720. {
  721. name <- res <- vector(mode="list",length=length(x))
  722. iw <- getOption("warn")
  723. options(warn=-1)
  724. on.exit(options(warn=iw))
  725. gdalPath <- getOption("MODIS_gdalPath")[1]
  726. gdalPath <- correctPath(gdalPath)
  727. cmd <- paste0(gdalPath,"gdalinfo ")
  728. for (i in seq_along(x))
  729. {
  730. tmp <- system(paste0(cmd,shQuote(x[i])),intern=TRUE)
  731. tmp <- grep(tmp,pattern="NoData Value=",value=TRUE)
  732. if (length(tmp)!=0)
  733. {
  734. res[[i]] <- as.numeric(strsplit(tmp,"=")[[1]][2])
  735. } else
  736. {
  737. res[[i]] <- NA
  738. }
  739. nam <- strsplit(x[i],":")[[1]]
  740. name[[i]] <- nam[length(nam)]
  741. }
  742. names(res) <- unlist(name)
  743. res[is.na(res)] <- NULL
  744. return(res)
  745. }
  746. correctPath <- function(x,isFile=FALSE)
  747. {
  748. if(!is.null(x))
  749. {
  750. if (.Platform$OS.type=="windows")
  751. {
  752. x <- gsub(utils::shortPathName(normalizePath(x,winslash="/",mustWork=FALSE)),pattern="\\\\",replacement="/")
  753. } else
  754. {
  755. x <- path.expand(x)
  756. }
  757. if (substr(x,nchar(x),nchar(x))!="/" & !isFile)
  758. {
  759. x <- paste0(x,"/")
  760. }
  761. x <- gsub(x,pattern="//",replacement="/")
  762. }
  763. return(x)
  764. }
  765. positionIndication = function(x) {
  766. product = suppressWarnings(getProduct(x, quiet = TRUE))
  767. if (!is.null(product)) {
  768. ids = as.integer(sapply(c("POS1", "POS2"), function(i) product[[i]]))
  769. pos = list("POS1" = ids[1], "POS2" = ids[2])
  770. return(pos)
  771. } else {
  772. stop("Either provide position indications or input files conforming to "
  773. , "MODIS standard naming convention.\n")
  774. }
  775. }
  776. # For further information, see https://lpdaac.usgs.gov/dataset_discovery/modis.
  777. getInfo = function(x, product = NULL, type = c("Tile", "CMG", "Swath")) {
  778. type = type[1]
  779. ## product short name (optional)
  780. if (is.null(product)) {
  781. product <- sapply(strsplit(basename(x), "\\."), "[[", 1)
  782. }
  783. ## julian date of acquisition
  784. # stringr::str_extract(x, "A[:digit:]{7}")
  785. doa = regmatches(x, regexpr("A[[:digit:]]{7}", x))
  786. ## time of acquisition
  787. if (type == "Swath") {
  788. toa = regmatches(x, regexpr("\\.[[:digit:]]{4}\\.", x))
  789. toa = gsub("\\.", "", toa)
  790. }
  791. ## tile identifier
  792. if (type == "Tile") {
  793. # stringr::str_extract(x, "h[0-3][0-9]v[0-1][0-9]")
  794. tid = regmatches(x, regexpr("h[0-3][0-9]v[0-1][0-9]", x))
  795. }
  796. ## collection version
  797. # stringr::str_extract(x, "\\.[:digit:]{3}\\.")
  798. ccc = regmatches(x, regexpr("\\.[[:digit:]]{3}\\.", x))
  799. ccc = gsub("\\.", "", ccc)
  800. ## julian date of production
  801. # stringr::str_extract(x, "\\.[:digit:]{13}\\.")
  802. dop = regmatches(x, regexpr("\\.[[:digit:]]{13}\\.", x))
  803. dop = gsub("\\.", "", dop)
  804. ## data format
  805. # stringr::str_extract(x, "\\.[:alpha:]{2,3}$")
  806. fmt = regmatches(x, regexpr("\\.[[:alpha:]]{2,3}$", x))
  807. fmt = gsub("\\.", "", fmt)
  808. ## set list names and return
  809. out = list(product, doa, tid, ccc, dop, fmt)
  810. names(out) = c("PRODUCT", "DATE", if (type == "Swath") "TIME"
  811. , if (type =="Tile") "TILE", "CCC", "PROCESSINGDATE", "FORMAT")
  812. return(out)
  813. }
  814. ## taken from https://cran.r-project.org/web/packages/maptools/vignettes/combine_maptools.pdf
  815. fixOrphanedHoles = function(x) {
  816. polys <- slot(x, "polygons")
  817. fixed <- lapply(polys, maptools::checkPolygonsHoles)
  818. sp::SpatialPolygons(fixed, proj4string = sp::CRS(sp::proj4string(x)))
  819. }
  820. ## skip unwanted products, see https://github.com/MatMatt/MODIS/issues/22
  821. skipDuplicateProducts = function(x, quiet = FALSE) {
  822. products = getProduct()[, 2]
  823. dpl = lapply(seq_along(products), function(i) {
  824. dpl = grep(products[i], products[-i], value = TRUE)
  825. if (length(dpl) > 0) {
  826. data.frame(product = products[i], duplicate = dpl)
  827. } else NULL
  828. })
  829. dpl = do.call(rbind, dpl)
  830. if (x %in% dpl$product) {
  831. if (!quiet) {
  832. warning("Processing ", x, " only. Use regular expressions (eg. '"
  833. , x, "*') to select more than one product.")
  834. }
  835. x = paste0("^", x, "$")
  836. }
  837. return(x)
  838. }