UsingMODISTools.Rnw 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. \documentclass[11pt]{article}
  2. \usepackage[top=2cm, bottom=3cm, left=2cm, right=2cm]{geometry}
  3. \usepackage[utf8]{inputenc}
  4. \usepackage{amsmath} % /eqref
  5. \usepackage{url}
  6. \usepackage{hyperref}
  7. \usepackage[none]{hyphenat} % No hyphens
  8. \usepackage[noae]{Sweave}
  9. %\VignetteIndexEntry{Using MODISTools}
  10. \newcommand{\code}[1]{\texttt{#1}}
  11. \begin{document}
  12. \sloppy % Prevent hyphenated words running into margins
  13. \SweaveOpts{concordance=TRUE, width=6, height=6}
  14. \setkeys{Gin}{width=0.5\textwidth}
  15. \title{Using MODISTools
  16. (\Sexpr{packageDescription('MODISTools', fields='Version')})}
  17. \author{Sean Tuck}
  18. \date{\Sexpr{packageDescription('MODISTools', fields='Date')}}
  19. \maketitle
  20. \tableofcontents
  21. <<echo=FALSE>>=
  22. library(MODISTools)
  23. # Makes copy-paste much less painful
  24. options(continue = ' ')
  25. options(width = 90)
  26. options(prompt = '> ')
  27. options(SweaveHooks = list(fig=function() par(mgp=c(2.5,1,0),
  28. mar=c(4,4,2,1),
  29. oma=c(0,0,1,0),
  30. cex.main=0.8)))
  31. @
  32. \section{Introduction}
  33. The MODISTools R package is a set of tools for downloading and working with NASA's MODIS remotely-sensed data. The package retrieves data from the LP DAAC data archive, via their SOAP web service. Functions download data as a batch process, and save subsets in text files that can be returned to at a later date. Additional functions can provide summaries of this data and prepare the data to a format ready for application in R; if you have other data that you wish to relate MODIS data to, downloaded data can be appended to your original dataset. Other ancillary functions can help to get input arguments into the correct format.
  34. This vignette provides a worked example for using MODISTools. A dataset of time-series -- lat-long coordinates with start and end dates -- to collect MODIS data for, will be used to show a complete workflow for how someone might use MODISTools. We will prepare input information for a subset request, download subsets of Enhanced Vegetation Index (EVI) and land cover data for the specified locations, and process these data to analyse land processes at these locations. Note that you will need an internet connection to run this worked example yourself, and that it will download files to your computer.
  35. \section{Format the data}
  36. We have some coordinates that we would like to extract MODIS data for. But the coordinates are not in the correct format. We need to make sure the coordinates we input for our subset request are in the WGS-1984 coordinate system, and are in decimal degrees format.
  37. <<>>=
  38. data(ConvertExample)
  39. ConvertExample
  40. @
  41. These coordinates are WGS-1984 coordinates, but they are not in decimal degrees. We can use \code{ConvertToDD} to fix this.
  42. <<>>=
  43. modis.subset <-
  44. ConvertToDD(XY = ConvertExample, LatColName = "lat", LongColName = "long")
  45. modis.subset <- data.frame(lat = modis.subset[ ,1], long = modis.subset[ ,2])
  46. modis.subset
  47. @
  48. What we also need to retrieve a time-series of MODIS data for these locations are dates. End dates for the time-series, and preferably start dates too. If we don't have start dates we can ask for a set number of years for each location instead. Let's retrieve data between 2003 and 2006. The dates can be specified as years or in POSIXlt date-time class (see \code{?POSIXlt}). In this case we can just use years.
  49. <<>>=
  50. modis.subset$start.date <- rep(2003, nrow(modis.subset))
  51. modis.subset$end.date <- rep(2006, nrow(modis.subset))
  52. @
  53. That's all we need! Let's download our EVI data first.
  54. \section{Download the data}
  55. \subsection{Specifying a subset request}
  56. The shortname code for the EVI product is ``MOD13Q1". We can check the codes for all the products available using \code{GetProducts}, and we can find the shortname codes for all data bands within each product using \code{GetBands}.
  57. <<eval=FALSE>>=
  58. GetProducts()
  59. @
  60. <<echo=FALSE>>=
  61. c("MCD12Q1", "MCD12Q2", "MCD43A1", "MCD43A2", "MCD43A4", "MOD09A1",
  62. "MOD11A2", "MOD13Q1", "MOD15A2", "MOD15A2GFS", "MOD16A2", "MOD17A2_51",
  63. "MOD17A3", "MYD09A1", "MYD11A2", "MYD13Q1", "MYD15A2")
  64. @
  65. <<eval=FALSE>>=
  66. GetBands(Product = "MOD13Q1")
  67. @
  68. <<echo=FALSE>>=
  69. c("250m_16_days_blue_reflectance", "250m_16_days_MIR_reflectance",
  70. "250m_16_days_NIR_reflectance", "250m_16_days_pixel_reliability",
  71. "250m_16_days_red_reflectance", "250m_16_days_relative_azimuth_angle",
  72. "250m_16_days_sun_zenith_angle", "250m_16_days_view_zenith_angle",
  73. "250m_16_days_VI_Quality", "250m_16_days_NDVI",
  74. "250m_16_days_EVI", "250m_16_days_composite_day_of_the_year")
  75. @
  76. We will download EVI data at 250m pixel resolution, which is available at 16-day intervals. The shortname code for this data band is 250m\_16\_days\_EVI. We will collect quality control data for these pixels too, which is available from the 250m\_16\_days\_pixel\_reliability band (and 250m\_16\_days\_VI\_Quality too).
  77. We can check that the time-series of MODIS data we want is available for this data product by retrieving the dates for all available time-steps.
  78. <<eval=FALSE>>=
  79. GetDates(Product = "MOD13Q1", Lat = modis.subset$lat[1], Long = modis.subset$long[1])
  80. @
  81. The time-period available for the Vegetation Indices product covers 2003-2006 (the maximum shown is at the time this vignette was built), so we can proceed. When we download we also need to decide how large we want the tiles of data for each location to be. We specify this by entering the distance (km) above and below in each direction away from the central pixel, where the input coordinate is located, and then doing the same for left and right. The input must be whole km (integers) for each direction. As an example, if we specify \code{Size=c(1,1)} for this EVI data at 250m pixel resolution, it will retrieve a 9x9 pixel tile for each location, centred on the input coordinate. The tiles this size will be downloaded at the locations for each time-step that falls between the start and end dates. \code{Size=c(0,0)} would specify only the central pixel. The maximum size tile surrounding a location is \code{Size=c(100,100)}.
  82. \subsection{MODISSubsets}
  83. The download will write the MODIS data to ASCII files for each location subset specified. We can specify the directory that we would like to save downloaded files in, using the \code{SaveDir} argument below. In the code below, downloaded files will be written to your working directory; if you would prefer the files to be written elsewhere change \code{SaveDir}. But we will access these files later, so remember to request the files from the same directory.
  84. <<eval=FALSE>>=
  85. MODISSubsets(LoadDat = modis.subset, Products = "MOD13Q1",
  86. Bands = c("250m_16_days_EVI", "250m_16_days_pixel_reliability"),
  87. Size = c(1,1))
  88. @
  89. Each ASCII file is a different subset location. In each ASCII file, each row is a different time-step in the time-series. If multiple data bands have been downloaded for this subset, they will all be contained in the same ASCII file for that subset.
  90. Here is an example of the strings of data that are downloaded for pixels at each time-step and data band:
  91. <<eval=FALSE>>=
  92. subset.string <- read.csv(list.files(pattern = ".asc")[1],
  93. header = FALSE, as.is = TRUE)
  94. subset.string[1, ]
  95. @
  96. <<echo=FALSE>>=
  97. subset.string <- read.csv(paste("./MODISSubsetsMOD13Q1/",
  98. list.files(path = "./MODISSubsetsMOD13Q1", pattern = ".asc")[1]
  99. , sep = ""), header = FALSE, as.is = TRUE)
  100. subset.string[1, ]
  101. @
  102. A download log file will also be written, displaying all the unique subsets found in the dataset, and confirmation of download success for each.
  103. \subsection{MODISTransects}
  104. Alternatively, we may want transects of MODIS data. This is easily done by specifying start and end points for transects, with unique IDs for each transect and then calling \code{MODISTransects} instead of using \code{MODISSubsets}. To try this out, use the example given in the \code{MODISTransects} help documentation.
  105. \section{Process the data}
  106. \subsection{MODISSummaries}
  107. Now we have downloaded the EVI data, we can find average each pixel over time, to produce one tile of mean EVI pixels at each subset location. We can use \code{MODISSummaries} for this. The function will also take this processed data and append it to your original files containing all the subset information (\code{modis.subset}). This will write two files to the specified directory. We downloaded quality control data for each pixel alongside our EVI data, so \code{MODISSummaries} can also check for poor quality and missing data. These data will be removed and replaced with \code{NA}s. The threshold for defining what is good and poor quality is set by the user: the scores for highest quality is 0, and the score for lowest quality is 3 or 5, depending on the data band. To see how quality control information is defined for each data type, go to the \href{https://daacweb-dev.ornl.gov/MODIS/MODIS-menu/products.html}{\bf{MODIS Products Table}}. We need to specify the range of valid data for EVI, the value that denotes missing data, and the scale factor that is applied to the data, which are all available from the same web page.
  108. <<eval=FALSE>>=
  109. MODISSummaries(LoadDat = modis.subset, Product = "MOD13Q1", Bands = "250m_16_days_EVI",
  110. ValidRange = c(-2000,10000), NoDataFill = -3000, ScaleFactor = 0.0001,
  111. QualityScreen = TRUE, QualityBand = "250m_16_days_pixel_reliability",
  112. QualityThreshold = 0)
  113. @
  114. If you want to screen data for quality without all the other things that \code{MODISSummaries} does, you can call the more general \code{QualityCheck}, which is an internal function for \code{MODISSummaries}.
  115. \subsection{ExtractTile}
  116. Also, if large subset tiles are downloaded for each location, there may be times when we want to extract a smaller tile from within this subset, rather than downloading again to retrieve the nested data we want. This can be done using \code{ExtractTile}. We will use the file just written from our call to \code{MODISSummaries}, retrieve the smaller subset we want, and arrange them into tiles to compare before and after.
  117. <<eval=FALSE>>=
  118. TileExample <- read.csv(list.files(pattern = "MODIS_Data"))
  119. TileExample <- TileExample[ ,which(grepl("250m_16_days_EVI", names(TileExample)))]
  120. @
  121. <<echo=FALSE>>=
  122. TileExample <- read.csv(paste("./MODISSummaries/",
  123. list.files(path = "./MODISSummaries/",
  124. pattern = "Data"), sep = ""))
  125. TileExample <- TileExample[ ,which(grepl("250m_16_days_EVI", names(TileExample)))]
  126. @
  127. Pixels in a tile are on the same row. See that using \code{ExtractTile} takes away some of the columns.
  128. <<>>=
  129. dim(TileExample)
  130. dim(ExtractTile(Data = TileExample, Rows = c(9,2), Cols = c(9,2), Grid = FALSE))
  131. head(ExtractTile(Data = TileExample, Rows = c(9,2), Cols = c(9,2), Grid = FALSE),
  132. n = 2)
  133. @
  134. We can look at the first subset and arrange the pixels into a tile to visually show what \code{ExtractTile} has done.
  135. <<>>=
  136. matrix(TileExample[1, ], nrow = 9, ncol = 9, byrow = TRUE)
  137. ExtractTile(Data = TileExample, Rows = c(9,2), Cols = c(9,2), Grid = TRUE)[ , ,1]
  138. @
  139. Arrangement of the pixels into tiles this way can be optionally set with a call to \code{ExtractTile}. The order for the strings of pixel data in the downloaded ASCII files is by row, so \code{matrix(..., byrow=TRUE)} can arrange the pixels correctly (see above).
  140. \subsection{LandCover}
  141. Let's do the same as above but download data on land cover classes for the same subsets.
  142. <<eval=FALSE>>=
  143. dir.create('./LandCover')
  144. setwd('./LandCover')
  145. MODISSubsets(LoadDat = modis.subset, Product = "MCD12Q1", Bands = "Land_Cover_Type_1",
  146. Size = c(1,1))
  147. @
  148. We can use \code{LandCover} to retrieve some summaries of land cover in each tile. This will tell us the most common land cover type, the total number of distinct land cover types, and Simpson's D and evenness measures to express landscape diversity and heterogeneity in these tiles. Let's retrieve these summaries from the land cover subset files we just downloaded.
  149. <<eval=FALSE>>=
  150. LandCover(Band = "Land_Cover_Type_1")
  151. land.summary <- read.csv(list.files(pattern = "MODIS_Land_Cover_Summary"))
  152. head(land.summary)
  153. @
  154. <<echo=FALSE>>=
  155. land.summary <- read.csv(paste("./LandCover/",
  156. list.files(path = "./LandCover/",
  157. pattern = "LandCoverSummary"),
  158. sep = ""))
  159. head(land.summary)
  160. @
  161. \end{document}