Load packages:

library(tidyverse)
library(lubridate)
library(readr)
library(tibble)
library(ggplot2)

0.1 Learning goals

  1. Register for a free NASA Earthdata account and access AppEEARS.
  2. Distinguish point and area extraction requests.
  3. Select MODIS products based on the variable, pixel size, and observation frequency.
  4. Download satellite data and make a basic time-series plot in R.
  5. Explain at least two limitations of using satellite products for watershed questions.

1 What is AppEEARS?

NASA AppEEARS (Application for Extracting and Exploring Analysis Ready Samples) is a web application for extracting environmental data at selected coordinates or within polygons. It allows you to specify where, when, and which satellite-derived variables you want. It can return values and quality information, with preview tools before download.

You do not need to write code to request data. We will use R only after downloading a file.

2 Create a free NASA Earthdata account

  1. Open NASA Earthdata Login.
  2. Select Register and complete the registration form.
  3. Activate your account using the link in the confirmation email.
  4. Open AppEEARS and sign in using your Earthdata credentials.

If you already have an Earthdata account, use your existing login.

3 MODIS: Which product should you choose?

MODIS (Moderate Resolution Imaging Spectroradiometer) instruments flew on the Terra and Aqua satellites. Product codes help identify their sources: MOD usually refers to Terra, MYD to Aqua, and MCD to combined Terra/Aqua products. Products differ in their measured or modeled variable, spatial resolution, and time step.

The table below gives common examples; check the live AppEEARS product catalog for available collections, layers, and date coverage.

Product family Example code Approximate pixel size Temporal resolution What it represents
Vegetation indices (NDVI, EVI) MOD13Q1 250 m 16 days Vegetation greenness
Vegetation indices (NDVI, EVI) MOD13A1 500 m 16 days Greenness at coarser resolution
Vegetation indices (NDVI, EVI) MOD13A2 1 km 16 days Broad-scale greenness
Surface reflectance MOD09A1 500 m 8 days Spectral reflectance, useful for calculating indices
Land surface temperature MOD11A2 1 km 8 days Daytime/nighttime surface temperature
Snow cover MOD10A1 500 m Daily Snow cover / snow-related quality layers
Leaf area index (LAI) / FPAR MCD15A3H 500 m 4 days Vegetation canopy properties
Evapotranspiration MOD16A2GF 500 m 8 days Modeled evapotranspiration, gap-filled
Gross primary productivity MOD17A2HGF 500 m 8 days Modeled terrestrial plant productivity
Land cover MCD12Q1 500 m Annual Classified land-cover types
Burned area MCD64A1 500 m Monthly Satellite-detected burned area

Important: The listed temporal resolution is the product’s reporting or composite interval, not necessarily the number of cloud-free observations. Some layers require a scale factor or quality filtering. A satellite’s land surface temperature is not stream-water temperature, and MODIS terrestrial GPP is not aquatic GPP.

4 Request a time series for a point

  1. In AppEEARS, choose Extract > Point Sample and start a new request.
  2. Give the request a descriptive name (for example, Watershed_NDVI_2020_2025).
  3. Enter one or more locations manually on the map or upload a CSV of coordinates. Check the on-screen coordinate format; latitude and longitude must not be reversed.
  4. Choose a date range (for example, January 1, 2020–December 31, 2025).
  5. Search for MOD13Q1 and select the NDVI layer. Also select an appropriate quality layer, if available.
  6. Review the requested locations, dates, product version, and layers; submit the request.
  7. Under Explore, check the request status. Once processing finishes, preview and download the output, including metadata and quality information. Look for emails confirming the request when through and has been finished being processed.

Try a location relevant to your own project. If you need a starting point, choose a forested watershed, a lake basin, or a valley with a visible vegetation gradient.

4.1 Optional: Make a coordinate CSV in R

If you have a site list with ID, lat, long already you can also upload that site list file.

locations <- tibble(
  id = c("Incline", "Blackwood"),
  latitude = c(39.2412, 39.1111),
  longitude = c(-119.9394, -120.1808)
)

write_csv(locations, "appeears_locations_example.csv")

Before uploading, confirm that the CSV column names and format match the current AppEEARS upload instructions.

4.1.1 Point samples versus area samples

Point Sample: extracts the value of the raster pixel containing each coordinate. This is useful for a simple time series at a field site, but the pixel may include vegetation, bare ground, water, and other features beyond the sampling point.

Area Sample: extracts raster data over a polygon (for example, a watershed boundary), with options for spatial outputs and summaries. Choose Extract > Area Sample, draw or upload a polygon, select products and dates, and choose output settings. This is generally more appropriate when your research question concerns the whole watershed rather than a single location.

5 Import a downloaded time series into R

Download a point-sample CSV from AppEEARS. Often these will be in the zipped file.

##  [1] "ID"                                                                         
##  [2] "Latitude"                                                                   
##  [3] "Longitude"                                                                  
##  [4] "Date"                                                                       
##  [5] "MODIS_Tile"                                                                 
##  [6] "MOD13Q1_061_Line_Y_250m"                                                    
##  [7] "MOD13Q1_061_Sample_X_250m"                                                  
##  [8] "MOD13Q1_061__250m_16_days_NDVI"                                             
##  [9] "MOD13Q1_061__250m_16_days_VI_Quality"                                       
## [10] "MOD13Q1_061__250m_16_days_VI_Quality_bitmask"                               
## [11] "MOD13Q1_061__250m_16_days_VI_Quality_MODLAND"                               
## [12] "MOD13Q1_061__250m_16_days_VI_Quality_MODLAND_Description"                   
## [13] "MOD13Q1_061__250m_16_days_VI_Quality_VI_Usefulness"                         
## [14] "MOD13Q1_061__250m_16_days_VI_Quality_VI_Usefulness_Description"             
## [15] "MOD13Q1_061__250m_16_days_VI_Quality_Aerosol_Quantity"                      
## [16] "MOD13Q1_061__250m_16_days_VI_Quality_Aerosol_Quantity_Description"          
## [17] "MOD13Q1_061__250m_16_days_VI_Quality_Adjacent_cloud_detected"               
## [18] "MOD13Q1_061__250m_16_days_VI_Quality_Adjacent_cloud_detected_Description"   
## [19] "MOD13Q1_061__250m_16_days_VI_Quality_Atmosphere_BRDF_Correction"            
## [20] "MOD13Q1_061__250m_16_days_VI_Quality_Atmosphere_BRDF_Correction_Description"
## [21] "MOD13Q1_061__250m_16_days_VI_Quality_Mixed_Clouds"                          
## [22] "MOD13Q1_061__250m_16_days_VI_Quality_Mixed_Clouds_Description"              
## [23] "MOD13Q1_061__250m_16_days_VI_Quality_Land/Water_Mask"                       
## [24] "MOD13Q1_061__250m_16_days_VI_Quality_Land/Water_Mask_Description"           
## [25] "MOD13Q1_061__250m_16_days_VI_Quality_Possible_snow/ice"                     
## [26] "MOD13Q1_061__250m_16_days_VI_Quality_Possible_snow/ice_Description"         
## [27] "MOD13Q1_061__250m_16_days_VI_Quality_Possible_shadow"                       
## [28] "MOD13Q1_061__250m_16_days_VI_Quality_Possible_shadow_Description"
## Rows: 140
## Columns: 28
## $ ID                                                                          <chr> …
## $ Latitude                                                                    <dbl> …
## $ Longitude                                                                   <dbl> …
## $ Date                                                                        <date> …
## $ MODIS_Tile                                                                  <chr> …
## $ MOD13Q1_061_Line_Y_250m                                                     <dbl> …
## $ MOD13Q1_061_Sample_X_250m                                                   <dbl> …
## $ MOD13Q1_061__250m_16_days_NDVI                                              <dbl> …
## $ MOD13Q1_061__250m_16_days_VI_Quality                                        <dbl> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_bitmask                                <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_MODLAND                                <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_MODLAND_Description                    <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_VI_Usefulness                          <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_VI_Usefulness_Description              <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_Aerosol_Quantity                       <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_Aerosol_Quantity_Description           <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_Adjacent_cloud_detected                <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_Adjacent_cloud_detected_Description    <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_Atmosphere_BRDF_Correction             <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_Atmosphere_BRDF_Correction_Description <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_Mixed_Clouds                           <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_Mixed_Clouds_Description               <chr> …
## $ `MOD13Q1_061__250m_16_days_VI_Quality_Land/Water_Mask`                      <chr> …
## $ `MOD13Q1_061__250m_16_days_VI_Quality_Land/Water_Mask_Description`          <chr> …
## $ `MOD13Q1_061__250m_16_days_VI_Quality_Possible_snow/ice`                    <chr> …
## $ `MOD13Q1_061__250m_16_days_VI_Quality_Possible_snow/ice_Description`        <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_Possible_shadow                        <chr> …
## $ MOD13Q1_061__250m_16_days_VI_Quality_Possible_shadow_Description            <chr> …
## # A tibble: 6 × 28
##   ID        Latitude Longitude Date       MODIS_Tile MOD13Q1_061_Line_Y_250m
##   <chr>        <dbl>     <dbl> <date>     <chr>                        <dbl>
## 1 Blackwood     39.1     -120. 2023-09-30 h08v05                         426
## 2 Blackwood     39.1     -120. 2023-10-16 h08v05                         426
## 3 Blackwood     39.1     -120. 2023-11-01 h08v05                         426
## 4 Blackwood     39.1     -120. 2023-11-17 h08v05                         426
## 5 Blackwood     39.1     -120. 2023-12-03 h08v05                         426
## 6 Blackwood     39.1     -120. 2023-12-19 h08v05                         426
## # ℹ 22 more variables: MOD13Q1_061_Sample_X_250m <dbl>,
## #   MOD13Q1_061__250m_16_days_NDVI <dbl>,
## #   MOD13Q1_061__250m_16_days_VI_Quality <dbl>,
## #   MOD13Q1_061__250m_16_days_VI_Quality_bitmask <chr>,
## #   MOD13Q1_061__250m_16_days_VI_Quality_MODLAND <chr>,
## #   MOD13Q1_061__250m_16_days_VI_Quality_MODLAND_Description <chr>,
## #   MOD13Q1_061__250m_16_days_VI_Quality_VI_Usefulness <chr>, …

Find the columns containing date, location, NDVI, and quality. The next code block is a template: change the column names to match your file, and consult the product documentation for scale factors and fill values.

Organize NDVI observations and QA information

# Example ONLY: replace Date, Site, and NDVI with your actual columns.
# Apply product-specific scale factors and QA filtering first.

ndvi_dat <- dat %>%
  transmute(
    site = as.character(ID),
    date = as.Date(Date),

    # NDVI (already scaled by AppEEARS)
    ndvi = as.numeric(
      MOD13Q1_061__250m_16_days_NDVI
    ),

    # MODIS quality assessment information
    modland = MOD13Q1_061__250m_16_days_VI_Quality_MODLAND_Description,

    usefulness = MOD13Q1_061__250m_16_days_VI_Quality_VI_Usefulness_Description,

    aerosol = MOD13Q1_061__250m_16_days_VI_Quality_Aerosol_Quantity_Description,

    adjacent_cloud = MOD13Q1_061__250m_16_days_VI_Quality_Adjacent_cloud_detected_Description,

    mixed_clouds = MOD13Q1_061__250m_16_days_VI_Quality_Mixed_Clouds_Description,

    snow = `MOD13Q1_061__250m_16_days_VI_Quality_Possible_snow/ice_Description`,

    shadow = MOD13Q1_061__250m_16_days_VI_Quality_Possible_shadow_Description,

    land_water = `MOD13Q1_061__250m_16_days_VI_Quality_Land/Water_Mask_Description`
  )
ggplot(ndvi_dat, aes(x = date, y = ndvi)) +
  geom_point(aes(shape= usefulness)) +
  geom_line() +
  facet_wrap(~ site, scales = "free_x") +
  labs(x = "Date", y = "NDVI", title = "MODIS vegetation greenness") +
  theme_bw()

Note: MODIS NDVI layers commonly store scaled integers; for MOD13Q1, the documented scale factor is typically 0.0001. Confirm the specific layer metadata before multiplying values, and remove fill/invalid values. Do not assume the downloaded file has already been scaled or quality-filtered.

6 Interpret the data carefully

Before interpreting a graph, answer these questions:

For example, NDVI can be informative about broad vegetation changes, but it is not a direct measurement of groundwater availability or riparian water use. Similarly, land surface temperature is not a direct measurement of air or water temperature.

7 Useful resources