runMrt.R 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. #' Run MODIS Reprojection Tool with Specified Parameters
  2. #'
  3. #' @description
  4. #' Specifying input parameters, this function gets MODIS grid data from the
  5. #' archive (HTTP/FTP or local) and processes them with the 'MRT-grid' tool. See
  6. #' also the 'MRT' manual, available online via
  7. #' \url{https://lpdaac.usgs.gov/sites/default/files/public/mrt41_usermanual_032811.pdf},
  8. #' for further information.
  9. #'
  10. #' @param ... See Details.
  11. #'
  12. #' @details
  13. #' \describe{
  14. #' \tabular{rll}{
  15. #' \tab \code{product}\tab See \code{\link{getProduct}}.\cr
  16. #' \tab \code{begin}\tab See \code{\link{transDate}}.\cr
  17. #' \tab \code{end}\tab See \code{\link{transDate}}.\cr
  18. #' \tab \code{extent}\tab See \code{\link{getTile}}.\cr
  19. #' \tab \code{SDSstring}\tab See \code{\link{getSds}}. Default is to extract all
  20. #' SDS.\cr
  21. #' \tab \code{job}\tab \code{character}. Name of the current job for the
  22. #' creation of the output folder. If not specified, it is created in
  23. #' 'PRODUCT.COLLECTION_DATETIME'\cr
  24. #'
  25. #' \tab \code{localArcPath}\tab \code{character}. Defaults to
  26. #' \code{options("MODIS_localArcPath")}. Local path to look for and/or download
  27. #' MODIS files.\cr
  28. #' \tab \code{outDirPath}\tab \code{character}. Defaults to
  29. #' \code{options("MODIS_outDirPath")}. Root directory where to write \code{job}
  30. #' folder.\cr
  31. #'
  32. #' \tab \code{dataType}\tab \code{character}, defaults to \code{'GeoTiff'} (see
  33. #' \code{\link{MODISoptions}}. 'MRT' supports: \code{"raw binary"} (hdr+dat),
  34. #' \code{"HDF-EOS"} (hdf), and \code{"GeoTiff"} (tif). Any other format
  35. #' specified through \code{\link{MODISoptions}} or \code{dataType}, is switched
  36. #' to 'GeoTiff'.\cr
  37. #'
  38. #' \tab \code{outProj}\tab \code{character}, see 'MRT' manual.\cr
  39. #' \tab \code{zone}\tab Optional UTM zone number when \code{outProj = "UTM"}. If
  40. #' not set, it is autodetected. See 'MRT' manual.\cr
  41. #' \tab \code{projPara}\tab \code{character} in the form "6371007.18 0.00 0.00
  42. #' ...". For \code{outProj \%in\% c("GEO","SIN")}, it is autodetected. See 'MRT'
  43. #' manual.\cr
  44. #' \tab \code{datum}\tab \code{character}, defaults to 'NODATUM'. See 'MRT'
  45. #' manual.\cr
  46. #'
  47. #' \tab \code{mosaic}\tab \code{logical}, defaults to \code{TRUE}. Mosaic files
  48. #' or not? One case for setting \code{mosaic=FALSE} is a too large \code{extent}.
  49. #' HDF4 file supports max 2GB filesize, if crossed mosaicing process will fail.\cr
  50. #' \tab \code{anonym}\tab \code{logical}, defaults to \code{TRUE}. If
  51. #' \code{FALSE}, the job name is added at the end of the root filename.\cr
  52. #' \tab \code{quiet}\tab \code{logical}, defaults to \code{FALSE}. It is up to
  53. #' you to switch to 'boring' alias \code{FALSE}. Not fully implemented!\cr
  54. #' \tab \code{dlmethod}\tab default \code{options("MODIS_dlmethod")}. Argument
  55. #' passed to \code{\link{download.file}} (see \code{\link{MODISoptions}}).\cr
  56. #' \tab \code{stubbornness}\tab Default is \code{options("MODIS_stubborness")}. See \code{?MODISoptions}\cr
  57. #' }
  58. #' }
  59. #'
  60. #' @author
  61. #' Matteo Mattiuzzi and Forrest Stevens
  62. #'
  63. #' @seealso
  64. #' \code{\link{getHdf}}.
  65. #'
  66. #' @source
  67. #' You can obtain MRT-grid after registration from:
  68. #' \url{https://lpdaac.usgs.gov/tools/modis_reprojection_tool}.
  69. #'
  70. #' @examples
  71. #' \dontrun{
  72. #' runMrt( product="MOD11A1", extent="austria", begin="2010001", end="2010002", SDSstring="101",
  73. #' job="ExampleGEOdelme", outProj="GEO")
  74. #' runMrt( product="MOD11A1", extent="austria", begin="2010001", end="2010002", SDSstring="101",
  75. #' job="ExampleSINdelme", outProj="SIN")
  76. #' runMrt( product="MOD11A1", extent="austria", begin="2010001", end="2010002", SDSstring="101",
  77. #' job="ExampleUTMdelme", outProj="UTM")
  78. #' }
  79. #' @export runMrt
  80. #' @name runMrt
  81. runMrt <- function(...)
  82. {
  83. MODISoptions(save=FALSE)
  84. opts <- combineOptions(...)
  85. if (!opts$mrtOk)
  86. {
  87. stop("MRT path not set or MRT not installed on your system!")
  88. }
  89. opts$product <- getProduct(opts$product,quiet=TRUE)
  90. opts$product$CCC <- getCollection(opts$product,collection=opts$collection)
  91. tLimits <- transDate(begin=opts$begin,end=opts$end)
  92. opts$localArcPath <- setPath(opts$localArcPath)
  93. opts$outDirPath <- setPath(opts$outDirPath)
  94. if(!tolower(opts$dataFormat) %in% c('raw binary', 'hdf-eos', 'hdf4image','gtiff', 'geotiff'))
  95. {
  96. stop('dataFormat=\'',opts$dataFormat ,'\' is not supported by MRT (only \'raw binary\', \'HDF-EOS\' or \'GeoTiff\')')
  97. }
  98. ext <- getExtension(opts$dataFormat)
  99. ################################
  100. # Some defaults:
  101. if (is.null(opts$quiet)) {opts$quiet <- FALSE}
  102. if (is.null(opts$mosaic)) {opts$mosaic <- TRUE}
  103. if (is.null(opts$anonym)) {opts$anonym <- TRUE}
  104. opts$resamplingType <- checkResamplingType(opts$resamplingType,tool="mrt",quiet=TRUE)
  105. opts$outProj <- checkOutProj(opts$outProj,tool="mrt",quiet=TRUE)
  106. if (opts$outProj[1]=="asIn")
  107. {
  108. if(as.numeric(opts$product$CCC) > 3) # this fails if a COLLECTION is "025"...don't know if this exists!
  109. {
  110. opts$outProj <- list(short="SIN",long="Sinusoidal")
  111. } else
  112. {
  113. opts$outProj <- list(short="ISIN", long="Integerized Sinusoidal")
  114. }
  115. }
  116. cat("Output projection:", opts$outProj$long,"\n")
  117. if (opts$outProj$short=="UTM")
  118. {
  119. if (is.null(opts$zone))
  120. {
  121. cat("No UTM zone specified using MRT autodetection.\n")
  122. } else
  123. {
  124. cat("Using UTM zone:", opts$zone,"\n")
  125. }
  126. }
  127. cat("Output pixel size:", opts$pixelSize,"\n")
  128. cat("Resampling method:", opts$resamplingType,"\n")
  129. if (is.null(opts$datum))
  130. {
  131. cat("No Datum specified, using 'NODATUM'!\n")
  132. opts$datum <- "NODATUM"
  133. } else if (!toupper(opts$datum) %in% c("NAD27", "NAD83", "WGS66", "WGS72", "WGS84", "NODATUM"))
  134. {
  135. stop('"datum" must be one of: "NAD27", "NAD83", "WGS66", "WGS72", "WGS84" or "NODATUM"')
  136. }
  137. if (is.null(opts$projPara))
  138. {
  139. if(opts$outProj$short=="SIN") # maybe we should add other
  140. {
  141. opts$projPara <- "6371007.18 0.00 0.00 0.00 0.00 0.00 0.00 0.00 86400.00 0.00 0.00 0.00 0.00 0.00 0.00"
  142. } else
  143. {
  144. cat("No output projection parameters specified. Reprojecting with no Parameters!\n")
  145. opts$projPara <- "0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0"
  146. }
  147. } else
  148. {
  149. cat("Output projection parameters specified!\nUsing:\n ",opts$projPara,"\n")
  150. }
  151. for (z in 1:length(opts$product$PRODUCT))
  152. {
  153. if (opts$product$TYPE[z]=="CMG")
  154. {
  155. tileID="GLOBAL"
  156. ntiles=1
  157. } else
  158. {
  159. opts$extent <- getTile(x=opts$extent,tileH=opts$tileH,tileV=opts$tileV)
  160. ntiles <- length(opts$extent$tile)
  161. }
  162. todo <- paste(opts$product$PRODUCT[z],".",opts$product$CCC[[opts$product$PRODUCT[z]]],sep="")
  163. for(u in 1:length(todo))
  164. {
  165. if (is.null(opts$job))
  166. {
  167. opts$job <- paste(todo[u],"_",format(Sys.time(), "%Y%m%d%H%M%S"),sep="")
  168. cat("No 'job' name specified, generated (date/time based)):",opts$job,"\n")
  169. }
  170. outDir <- file.path(opts$outDirPath,opts$job,fsep="/")
  171. dir.create(outDir)
  172. ######################## along platform (TerraAqua)
  173. ftpdirs <- list() ## FRS: Fix provided by Ahmadou Dicko
  174. ftpdirs[[1]] <- as.Date(getStruc(product=strsplit(todo[u],"\\.")[[1]][1],collection=strsplit(todo[u],"\\.")[[1]][2],begin=tLimits$begin,end=tLimits$end,server=opts$MODISserverOrder[1])$dates)
  175. prodname <- strsplit(todo[u],"\\.")[[1]][1]
  176. coll <- strsplit(todo[u],"\\.")[[1]][2]
  177. avDates <- ftpdirs[[1]]
  178. avDates <- avDates[avDates!=FALSE]
  179. avDates <- avDates[!is.na(avDates)]
  180. sel <- as.Date(avDates)
  181. us <- sel >= tLimits$begin & sel <= tLimits$end
  182. if (sum(us,na.rm=TRUE)>0)
  183. {
  184. avDates <- avDates[us]
  185. ######################### along begin -> end date
  186. for (l in 1:length(avDates))
  187. {
  188. files <- unlist(getHdf(product=opts$product$PRODUCT[z],collection=strsplit(todo[u],"\\.")[[1]][2],begin=avDates[l],end=avDates[l],tileH=opts$extent$tileH,tileV=opts$extent$tileV,stubbornness=opts$stubbornness))
  189. if (length(files)!=0)
  190. {
  191. mos <- opts$mosaic
  192. if (mos)
  193. {
  194. # if not all files available switch "off" mosaicking and process single files. Problematic in areas with tiles outside land!
  195. if (sum(file.exists(files)) < length(opts$extent$tile))
  196. {
  197. mos <- FALSE
  198. } else {
  199. mos <- TRUE
  200. }
  201. } else {
  202. mos <- FALSE
  203. }
  204. if (mos)
  205. {
  206. v <- 1
  207. } else {
  208. v <- seq_along(files)
  209. }
  210. for (q in v)
  211. {
  212. w <- options("warn")
  213. options(warn=-1)
  214. if (is.null(opts$SDSstring))
  215. {
  216. opts$SDSstring <- rep(1,length(getSds(HdfName=files[q],method="mrt")$SDSnames))
  217. }
  218. SDSstringIntern <- getSds(HdfName=files[q],SDSstring=opts$SDSstring,method="mrt")
  219. options(warn=w$warn)
  220. if (!opts$quiet && u == 1 && l == 1)
  221. {
  222. cat("\n#############################\nExtracing SDS:",SDSstringIntern$SDSnames,"#############################\n",sep="\n")
  223. }
  224. if (mos)
  225. {
  226. TmpMosNam <- paste("TmpMosaic",makeRandomString(),".hdf",sep="")
  227. ### in subset
  228. paraname <- file.path(outDir,"/MRTgMosaic.prm",fsep="/") # create mosaic prm file
  229. filename = file(paraname, open="wt")
  230. write(paste("\"",files,"\"",sep='',collapse=' '), filename)
  231. close(filename)
  232. # run mosaic
  233. if (.Platform$OS=="unix")
  234. {
  235. system(paste("mrtmosaic -i ",paraname," -o ",outDir,"/",TmpMosNam," -s '",SDSstringIntern$SDSstring,"'" ,sep=""))
  236. } else
  237. {
  238. shell(paste("mrtmosaic -i \"",paraname,"\" -o \"", normalizePath(outDir) ,"\\",TmpMosNam,"\" -s \"",SDSstringIntern$SDSstring,"\"" ,sep=""))
  239. }
  240. unlink(paraname)
  241. Sys.sleep(opts$wait) # without wait the skript can break here. "wait" is a try but it seams to work!!!
  242. }
  243. basenam <- strsplit(files[q],"/")[[1]]
  244. basenam <- basenam[length(basenam)]
  245. if (mos)
  246. {
  247. basenam <- paste(strsplit(basenam,"\\.")[[1]][c(1,2,4)],collapse=".")
  248. } else {
  249. basenam <- paste(strsplit(basenam,"\\.")[[1]][c(1,2,3,4)],collapse=".")
  250. }
  251. if (!opts$anonym)
  252. {
  253. basenam <- paste(basenam,opts$job,sep=".")
  254. }
  255. #### Write prm File
  256. paraname <- paste(outDir,"/MRTgResample.prm",sep="")
  257. filename = file(paraname, open="wt")
  258. if (mos)
  259. {
  260. write(paste('INPUT_FILENAME = "',outDir,"/",TmpMosNam,'"',sep=''), filename)
  261. } else
  262. {
  263. write(paste('SPECTRAL_SUBSET = ( ',SDSstringIntern$SDSstring,' )',sep=''), filename)
  264. write(paste('INPUT_FILENAME = "',files[q],'"',sep=''), filename)
  265. }
  266. write('SPATIAL_SUBSET_TYPE = INPUT_LAT_LONG',filename)
  267. if (!is.null(opts$extent$extent))
  268. {
  269. write(paste('SPATIAL_SUBSET_UL_CORNER = (',opts$extent$extent@ymax,' ',opts$extent$extent@xmin,')',sep=''),filename)
  270. write(paste('SPATIAL_SUBSET_LR_CORNER = (',opts$extent$extent@ymin,' ',opts$extent$extent@xmax,')',sep=''),filename)
  271. }
  272. if (opts$pixelSize!="asIn")
  273. {
  274. write(paste('OUTPUT_PIXEL_SIZE = ',opts$pixelSize,sep=''),filename)
  275. }
  276. write(paste('OUTPUT_FILENAME = ',outDir,"/",basenam,ext,sep=''),filename)
  277. write(paste('RESAMPLING_TYPE = ',opts$resamplingType,sep=''),filename)
  278. write(paste('OUTPUT_PROJECTION_TYPE = ',opts$outProj$short,sep=''),filename)
  279. if (opts$outProj$short=="UTM" && !is.null(opts$zone))
  280. {
  281. write(paste('UTM_ZONE = ',opts$zone,sep=''),filename)
  282. }
  283. if (!is.null(opts$projPara))
  284. {
  285. write(paste('OUTPUT_PROJECTION_PARAMETERS = ( ',opts$projPara,' )',sep=''),filename)
  286. }
  287. if (!is.null(opts$datum))
  288. {
  289. write(paste('DATUM =', opts$datum,sep=''),filename)
  290. }
  291. close(filename)
  292. if (.Platform$OS=="unix")
  293. {
  294. system(paste("resample -p ",paraname,sep=""))
  295. } else {
  296. shell(paste("resample -p \"",paraname,"\" -o \"",outDir,"/",basenam, ext,sep=""))
  297. }
  298. unlink(paraname)
  299. if (mos)
  300. {
  301. unlink(paste(outDir,TmpMosNam,sep="/"))
  302. }
  303. }
  304. } else {
  305. cat("Missing files on",avDates[l],"jumping to the next date",sep="\n")
  306. }
  307. } # l, avDates
  308. } else {
  309. cat("No files found for",todo[u],"within the date range\n")
  310. }
  311. } # u
  312. }
  313. }