inst/doc/vegetation-indices.R

## ----setup, include = FALSE---------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 8,
  fig.height = 6,
  warning = FALSE,
  message = FALSE
)

## ----eval=FALSE---------------------------------------------------------------
# library(geospatialsuite)
# 
# # See all available vegetation indices
# all_indices <- list_vegetation_indices()
# print(all_indices)
# 
# # View detailed information with formulas
# detailed_indices <- list_vegetation_indices(detailed = TRUE)
# head(detailed_indices)
# 
# # Filter by category
# basic_indices <- list_vegetation_indices(category = "basic")
# stress_indices <- list_vegetation_indices(category = "stress")

## ----complete-index-table, echo=FALSE, message=FALSE--------------------------
library(geospatialsuite)
detailed <- list_vegetation_indices(detailed = TRUE)

knitr::kable(
  detailed[, c("Index", "Category", "Formula", "Range", "Reference")],
  caption = "Complete Vegetation Indices Reference - All 62 Indices",
  format = "html"
)

## ----index-info-example, eval=FALSE-------------------------------------------
# # Get all indices with formulas
# all_indices <- list_vegetation_indices(detailed = TRUE)
# View(all_indices)
# 
# # Filter by category
# stress <- list_vegetation_indices(category = "stress", detailed = TRUE)
# water <- list_vegetation_indices(application = "water", detailed = TRUE)
# 
# # Get specific index information
# ndvi_info <- all_indices[all_indices$Index == "NDVI", ]
# cat(sprintf("NDVI Formula: %s\n", ndvi_info$Formula))
# cat(sprintf("NDVI Range: %s\n", ndvi_info$Range))
# cat(sprintf("Reference: %s\n", ndvi_info$Reference))

## ----eval=FALSE---------------------------------------------------------------
# # Simple NDVI from individual bands
# ndvi <- calculate_vegetation_index(
#   red = "landsat_red.tif",
#   nir = "landsat_nir.tif",
#   index_type = "NDVI",
#   verbose = TRUE
# )
# 
# # View results
# terra::plot(ndvi, main = "NDVI Analysis",
#             col = colorRampPalette(c("brown", "yellow", "green"))(100))
# 
# # Check value range
# summary(terra::values(ndvi, mat = FALSE))

## ----eval=FALSE---------------------------------------------------------------
# # Calculate multiple vegetation indices
# vegetation_stack <- calculate_multiple_indices(
#   red = red_band,
#   nir = nir_band,
#   blue = blue_band,
#   green = green_band,
#   indices = c("NDVI", "EVI", "SAVI", "GNDVI", "DVI", "RVI"),
#   output_stack = TRUE,
#   region_boundary = "Ohio",
#   verbose = TRUE
# )
# 
# # Access individual indices
# ndvi_layer <- vegetation_stack$NDVI
# evi_layer <- vegetation_stack$EVI
# 
# # Create comparison visualization
# terra::plot(vegetation_stack, main = names(vegetation_stack))

## ----eval=FALSE---------------------------------------------------------------
# # From multi-band raster with auto-detection
# evi <- calculate_vegetation_index(
#   spectral_data = "sentinel2_image.tif",
#   index_type = "EVI",
#   auto_detect_bands = TRUE,
#   verbose = TRUE
# )
# 
# # From directory with band detection
# savi <- calculate_vegetation_index(
#   spectral_data = "/path/to/sentinel/bands/",
#   index_type = "SAVI",
#   auto_detect_bands = TRUE
# )
# 
# # Custom band names for non-standard data
# ndvi_custom <- calculate_vegetation_index(
#   spectral_data = custom_satellite_data,
#   band_names = c("B4", "B3", "B2", "B8"),  # Red, Green, Blue, NIR
#   index_type = "NDVI"
# )

## ----eval=FALSE---------------------------------------------------------------
# # Time series NDVI with quality control
# ndvi_series <- calculate_ndvi_enhanced(
#   red_data = "/path/to/red/time_series/",
#   nir_data = "/path/to/nir/time_series/",
#   match_by_date = TRUE,           # Automatically match files by date
#   quality_filter = TRUE,          # Remove outliers
#   temporal_smoothing = TRUE,      # Smooth time series
#   clamp_range = c(-0.2, 1),
#   verbose = TRUE
# )
# 
# # Plot time series layers
# terra::plot(ndvi_series, main = paste("NDVI", names(ndvi_series)))
# 
# # Calculate temporal statistics
# temporal_mean <- terra::app(ndvi_series, mean, na.rm = TRUE)
# temporal_cv <- terra::app(ndvi_series, function(x) sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE))

## ----eval=FALSE---------------------------------------------------------------
# # Temporal analysis workflow
# temporal_results <- analyze_temporal_changes(
#   data_list = c("ndvi_2020.tif", "ndvi_2021.tif", "ndvi_2022.tif", "ndvi_2023.tif"),
#   dates = c("2020", "2021", "2022", "2023"),
#   region_boundary = "Iowa",
#   analysis_type = "trend",
#   output_folder = "temporal_analysis/"
# )
# 
# # Access trend results
# slope_raster <- temporal_results$trend_rasters$slope
# r_squared_raster <- temporal_results$trend_rasters$r_squared
# 
# # Interpret trends
# # Positive slope = increasing vegetation
# # Negative slope = declining vegetation
# # High R² = strong temporal trend

## ----eval=FALSE---------------------------------------------------------------
# # Comprehensive crop vegetation analysis
# corn_analysis <- analyze_crop_vegetation(
#   spectral_data = "sentinel2_data.tif",
#   crop_type = "corn",
#   growth_stage = "mid",
#   analysis_type = "comprehensive",
#   cdl_mask = corn_mask,
#   verbose = TRUE
# )
# 
# # Access results
# vegetation_indices <- corn_analysis$vegetation_indices
# stress_analysis <- corn_analysis$analysis_results$stress_analysis
# yield_analysis <- corn_analysis$analysis_results$yield_analysis
# 
# # View stress detection results
# print(stress_analysis$NDVI)

## ----eval=FALSE---------------------------------------------------------------
# # Early season analysis (emergence to vegetative)
# early_season <- analyze_crop_vegetation(
#   spectral_data = "may_sentinel2.tif",
#   crop_type = "soybeans",
#   growth_stage = "early",
#   analysis_type = "growth"
# )
# 
# # Mid-season analysis (reproductive stage)
# mid_season <- analyze_crop_vegetation(
#   spectral_data = "july_sentinel2.tif",
#   crop_type = "soybeans",
#   growth_stage = "mid",
#   analysis_type = "stress"
# )
# 
# # Compare growth stages
# early_ndvi <- early_season$vegetation_indices$NDVI
# mid_ndvi <- mid_season$vegetation_indices$NDVI
# growth_change <- mid_ndvi - early_ndvi

## ----eval=FALSE---------------------------------------------------------------
# # Calculate stress-sensitive indices
# stress_indices <- calculate_multiple_indices(
#   red = red_band,
#   nir = nir_band,
#   green = green_band,
#   red_edge = red_edge_band,     # If available
#   indices = c("NDVI", "PRI", "SIPI", "NDRE"),
#   output_stack = TRUE
# )
# 
# # Stress analysis thresholds
# ndvi_values <- terra::values(stress_indices$NDVI, mat = FALSE)
# healthy_threshold <- 0.6
# stress_threshold <- 0.4
# 
# # Classify stress levels
# stress_mask <- terra::classify(stress_indices$NDVI,
#                                matrix(c(-1, stress_threshold, 1,      # Severe stress
#                                        stress_threshold, healthy_threshold, 2,  # Moderate stress
#                                        healthy_threshold, 1, 3), ncol = 3, byrow = TRUE))
# 
# # Visualization
# stress_colors <- c("red", "orange", "green")
# terra::plot(stress_mask, main = "Vegetation Stress Classification",
#             col = stress_colors, legend = c("Severe", "Moderate", "Healthy"))

## ----eval=FALSE---------------------------------------------------------------
# # Water content indices
# water_stress <- calculate_multiple_indices(
#   nir = nir_band,
#   swir1 = swir1_band,
#   indices = c("NDMI", "MSI", "NDII"),
#   output_stack = TRUE
# )
# 
# # NDMI interpretation:
# # High NDMI (>0.4) = High water content
# # Low NDMI (<0.1) = Water stress
# 
# # MSI interpretation (opposite of NDMI):
# # Low MSI (<1.0) = High moisture
# # High MSI (>1.6) = Water stress
# 
# # Create water stress map
# water_stress_binary <- terra::classify(water_stress$NDMI,
#                                        matrix(c(-1, 0.1, 1,    # Water stress
#                                                0.1, 0.4, 2,    # Moderate
#                                                0.4, 1, 3), ncol = 3, byrow = TRUE))

## ----eval=FALSE---------------------------------------------------------------
# # Enhanced NDVI with quality filtering
# ndvi_quality <- calculate_ndvi_enhanced(
#   red_data = red_raster,
#   nir_data = nir_raster,
#   quality_filter = TRUE,          # Remove outliers
#   clamp_range = c(-0.2, 1),      # Reasonable NDVI range
#   temporal_smoothing = FALSE,     # For single date
#   verbose = TRUE
# )
# 
# # Custom quality filtering
# vegetation_filtered <- calculate_vegetation_index(
#   red = red_band,
#   nir = nir_band,
#   index_type = "NDVI",
#   mask_invalid = TRUE,            # Remove invalid values
#   clamp_range = c(-1, 1)         # Theoretical NDVI range
# )

## ----eval=FALSE---------------------------------------------------------------
# # Compare with field measurements
# field_ndvi_validation <- universal_spatial_join(
#   source_data = "field_measurements.csv",  # Ground truth points
#   target_data = ndvi_raster,              # Satellite NDVI
#   method = "extract",
#   buffer_distance = 30,                   # 30m buffer around points
#   summary_function = "mean"
# )
# 
# # Calculate correlation
# observed <- field_ndvi_validation$field_ndvi
# predicted <- field_ndvi_validation$extracted_NDVI
# 
# correlation <- cor(observed, predicted, use = "complete.obs")
# rmse <- sqrt(mean((observed - predicted)^2, na.rm = TRUE))
# 
# print(paste("Validation R =", round(correlation, 3)))
# print(paste("RMSE =", round(rmse, 4)))

## ----eval=FALSE---------------------------------------------------------------
# # Create NDVI time series for phenology
# phenology_analysis <- analyze_temporal_changes(
#   data_list = list.files("/ndvi/2023/", pattern = "*.tif", full.names = TRUE),
#   dates = extract_dates_universal(list.files("/ndvi/2023/", pattern = "*.tif")),
#   region_boundary = "Iowa",
#   analysis_type = "seasonal",
#   output_folder = "phenology_results/"
# )
# 
# # Access seasonal patterns
# spring_ndvi <- phenology_analysis$seasonal_rasters$Spring
# summer_ndvi <- phenology_analysis$seasonal_rasters$Summer
# fall_ndvi <- phenology_analysis$seasonal_rasters$Fall
# 
# # Calculate growing season metrics
# peak_season <- terra::app(c(spring_ndvi, summer_ndvi), max, na.rm = TRUE)
# growing_season_range <- summer_ndvi - spring_ndvi

## ----eval=FALSE---------------------------------------------------------------
# # Landsat NDVI (30m resolution)
# landsat_ndvi <- calculate_vegetation_index(
#   red = "landsat8_red.tif",
#   nir = "landsat8_nir.tif",
#   index_type = "NDVI"
# )
# 
# # MODIS NDVI (250m resolution)
# modis_ndvi <- calculate_vegetation_index(
#   red = "modis_red.tif",
#   nir = "modis_nir.tif",
#   index_type = "NDVI"
# )
# 
# # Resample MODIS to Landsat resolution for comparison
# modis_resampled <- universal_spatial_join(
#   source_data = modis_ndvi,
#   target_data = landsat_ndvi,
#   method = "resample",
#   summary_function = "bilinear"
# )
# 
# # Compare sensors
# sensor_difference <- landsat_ndvi - modis_resampled
# correlation <- calculate_spatial_correlation(landsat_ndvi, modis_resampled)

## ----eval=FALSE---------------------------------------------------------------
# # Forest-specific indices
# forest_indices <- calculate_multiple_indices(
#   red = red_band,
#   nir = nir_band,
#   swir1 = swir1_band,
#   swir2 = swir2_band,
#   indices = c("NDVI", "EVI", "NBR", "NDMI"),  # Normalized Burn Ratio, moisture
#   region_boundary = "forest_boundary.shp",
#   output_stack = TRUE
# )
# 
# # Burn severity assessment using NBR
# pre_fire_nbr <- forest_indices$NBR  # Before fire
# post_fire_nbr <- calculate_vegetation_index(
#   red = "post_fire_red.tif",
#   nir = "post_fire_nir.tif",
#   swir2 = "post_fire_swir2.tif",
#   index_type = "NBR"
# )
# 
# # Calculate burn severity (dNBR)
# burn_severity <- pre_fire_nbr - post_fire_nbr
# 
# # Classify burn severity
# severity_classes <- terra::classify(burn_severity,
#   matrix(c(-Inf, 0.1, 1,      # Unburned
#            0.1, 0.27, 2,       # Low severity
#            0.27, 0.44, 3,      # Moderate-low
#            0.44, 0.66, 4,      # Moderate-high
#            0.66, Inf, 5), ncol = 3, byrow = TRUE))

## ----eval=FALSE---------------------------------------------------------------
# # Grassland-specific analysis
# grassland_health <- calculate_multiple_indices(
#   red = red_band,
#   nir = nir_band,
#   green = green_band,
#   indices = c("NDVI", "SAVI", "MSAVI", "GNDVI"),  # Soil-adjusted indices
#   output_stack = TRUE
# )
# 
# # Analyze grazing impact
# grazed_area_ndvi <- terra::mask(grassland_health$NDVI, grazing_areas)
# ungrazed_area_ndvi <- terra::mask(grassland_health$NDVI, ungrazed_areas)
# 
# # Compare means
# grazed_mean <- terra::global(grazed_area_ndvi, "mean", na.rm = TRUE)
# ungrazed_mean <- terra::global(ungrazed_area_ndvi, "mean", na.rm = TRUE)
# 
# grazing_impact <- ungrazed_mean - grazed_mean

## ----eval=FALSE---------------------------------------------------------------
# # Urban vegetation analysis with atmospheric correction
# urban_vegetation <- calculate_vegetation_index(
#   red = urban_red,
#   nir = urban_nir,
#   blue = urban_blue,
#   index_type = "ARVI",           # Atmospherically Resistant VI
#   region_boundary = "city_boundary.shp"
# )
# 
# # Green space analysis
# green_space_threshold <- 0.3
# urban_greenness <- terra::classify(urban_vegetation,
#   matrix(c(-1, green_space_threshold, 0,           # Non-vegetated
#            green_space_threshold, 1, 1), ncol = 3, byrow = TRUE))  # Vegetated
# 
# # Calculate green space statistics
# total_urban_area <- terra::ncell(urban_greenness) * prod(terra::res(urban_greenness))
# green_area <- terra::global(urban_greenness, "sum", na.rm = TRUE) * prod(terra::res(urban_greenness))
# green_space_percentage <- (green_area / total_urban_area) * 100

## ----eval=FALSE---------------------------------------------------------------
# ndvi <- calculate_vegetation_index(red = red, nir = nir, index_type = "NDVI")

## ----eval=FALSE---------------------------------------------------------------
# evi <- calculate_vegetation_index(red = red, nir = nir, blue = blue, index_type = "EVI")

## ----eval=FALSE---------------------------------------------------------------
# savi <- calculate_vegetation_index(red = red, nir = nir, index_type = "SAVI")

## ----eval=FALSE---------------------------------------------------------------
# # Note: PRI typically uses 531nm and 570nm bands
# # Using green and NIR as approximation
# pri <- calculate_vegetation_index(green = green, nir = nir, index_type = "PRI")

## ----eval=FALSE---------------------------------------------------------------
# crop_health <- calculate_multiple_indices(
#   red = red, nir = nir, green = green,
#   indices = c("NDVI", "GNDVI", "SIPI"),  # Structure Insensitive Pigment Index
#   output_stack = TRUE
# )

## ----eval=FALSE---------------------------------------------------------------
# drought_indices <- calculate_multiple_indices(
#   nir = nir, swir1 = swir1,
#   indices = c("NDMI", "MSI"),  # Moisture indices
#   output_stack = TRUE
# )

## ----eval=FALSE---------------------------------------------------------------
# precision_ag <- calculate_multiple_indices(
#   red = red, nir = nir, green = green, red_edge = red_edge,
#   indices = c("NDVI", "NDRE", "GNDVI", "CCI"),  # Chlorophyll indices
#   output_stack = TRUE
# )

## ----eval=FALSE---------------------------------------------------------------
# # NDVI-specific visualization
# create_spatial_map(
#   spatial_data = ndvi_raster,
#   color_scheme = "ndvi",          # NDVI-specific colors
#   region_boundary = "study_area.shp",
#   title = "NDVI Analysis - Growing Season Peak",
#   output_file = "ndvi_analysis.png"
# )
# 
# # Multi-index comparison
# create_comparison_map(
#   data1 = ndvi_raster,
#   data2 = evi_raster,
#   comparison_type = "side_by_side",
#   titles = c("NDVI", "EVI"),
#   color_scheme = "viridis"
# )

## ----eval=FALSE---------------------------------------------------------------
# # Interactive vegetation analysis
# interactive_veg_map <- create_interactive_map(
#   spatial_data = vegetation_points,
#   fill_variable = "NDVI",
#   popup_vars = c("NDVI", "EVI", "collection_date"),
#   basemap = "satellite",
#   title = "Interactive Vegetation Analysis"
# )
# 
# # Save interactive map
# htmlwidgets::saveWidget(interactive_veg_map, "vegetation_interactive.html")

## ----eval=FALSE---------------------------------------------------------------
# # Calculate comprehensive statistics
# vegetation_stats <- terra::global(vegetation_stack,
#                                   c("mean", "sd", "min", "max"),
#                                   na.rm = TRUE)
# 
# print(vegetation_stats)
# 
# # Zonal statistics by land cover
# landcover_stats <- universal_spatial_join(
#   source_data = vegetation_stack,
#   target_data = "landcover_polygons.shp",
#   method = "zonal",
#   summary_function = "mean"
# )
# 
# # Statistics by vegetation class
# healthy_vegetation <- vegetation_stack$NDVI > 0.6
# moderate_vegetation <- vegetation_stack$NDVI > 0.3 & vegetation_stack$NDVI <= 0.6
# poor_vegetation <- vegetation_stack$NDVI <= 0.3
# 
# # Calculate percentages
# total_pixels <- terra::ncell(vegetation_stack$NDVI)
# healthy_pct <- terra::global(healthy_vegetation, "sum", na.rm = TRUE) / total_pixels * 100
# moderate_pct <- terra::global(moderate_vegetation, "sum", na.rm = TRUE) / total_pixels * 100
# poor_pct <- terra::global(poor_vegetation, "sum", na.rm = TRUE) / total_pixels * 100

## ----eval=FALSE---------------------------------------------------------------
# # Analyze relationships between indices
# index_correlations <- analyze_variable_correlations(
#   variable_list = list(
#     NDVI = vegetation_stack$NDVI,
#     EVI = vegetation_stack$EVI,
#     SAVI = vegetation_stack$SAVI,
#     GNDVI = vegetation_stack$GNDVI
#   ),
#   method = "pearson",
#   create_plots = TRUE,
#   output_folder = "correlation_analysis/"
# )
# 
# # View correlation matrix
# print(index_correlations$correlation_matrix)

## ----eval=FALSE---------------------------------------------------------------
# # 1. Define study area
# study_area <- get_region_boundary("Iowa:Story")  # Story County, Iowa
# 
# # 2. Create corn mask
# corn_mask <- create_crop_mask(
#   cdl_data = "cdl_iowa_2023.tif",
#   crop_codes = get_comprehensive_cdl_codes("corn"),
#   region_boundary = study_area
# )
# 
# # 3. Calculate vegetation indices for corn areas
# corn_vegetation <- calculate_multiple_indices(
#   spectral_data = "sentinel2_iowa_july.tif",
#   indices = c("NDVI", "EVI", "GNDVI", "SAVI"),
#   auto_detect_bands = TRUE,
#   output_stack = TRUE
# )
# 
# # 4. Apply corn mask
# corn_vegetation_masked <- terra::mask(corn_vegetation, corn_mask)
# 
# # 5. Analyze corn health
# corn_stats <- terra::global(corn_vegetation_masked,
#                            c("mean", "sd", "min", "max"),
#                            na.rm = TRUE)
# 
# # 6. Create visualization
# quick_map(corn_vegetation_masked$NDVI,
#           title = "Story County Corn NDVI - July 2023")
# 
# # 7. Save results
# terra::writeRaster(corn_vegetation_masked, "story_county_corn_indices.tif")

## ----eval=FALSE---------------------------------------------------------------
# # 1. Load multi-temporal data
# april_data <- calculate_ndvi_enhanced("april_sentinel2.tif")
# july_data <- calculate_ndvi_enhanced("july_sentinel2.tif")
# 
# # 2. Calculate stress indices
# stress_indices <- calculate_multiple_indices(
#   spectral_data = "july_sentinel2.tif",
#   indices = c("NDVI", "PRI", "SIPI", "NDMI"),
#   auto_detect_bands = TRUE,
#   output_stack = TRUE
# )
# 
# # 3. Identify stressed areas
# # NDVI decline from April to July
# ndvi_change <- july_data - april_data
# stress_areas <- ndvi_change < -0.2  # Significant decline
# 
# # Water stress (low NDMI)
# water_stress <- stress_indices$NDMI < 0.2
# 
# # Combined stress map
# combined_stress <- stress_areas | water_stress
# 
# # 4. Quantify stress
# total_area <- terra::ncell(combined_stress) * prod(terra::res(combined_stress)) / 10000  # hectares
# stressed_pixels <- terra::global(combined_stress, "sum", na.rm = TRUE)
# stressed_area <- stressed_pixels * prod(terra::res(combined_stress)) / 10000  # hectares
# stress_percentage <- (stressed_area / total_area) * 100
# 
# print(paste("Stressed area:", round(stressed_area, 1), "hectares"))
# print(paste("Stress percentage:", round(stress_percentage, 1), "%"))

## ----eval=FALSE---------------------------------------------------------------
# # 1. Multi-state analysis
# great_lakes_states <- c("Michigan", "Ohio", "Indiana", "Illinois", "Wisconsin")
# 
# regional_ndvi <- list()
# for (state in great_lakes_states) {
#   state_ndvi <- calculate_vegetation_index(
#     spectral_data = paste0("/data/", tolower(state), "_modis.tif"),
#     index_type = "NDVI",
#     region_boundary = state,
#     auto_detect_bands = TRUE
#   )
#   regional_ndvi[[state]] <- state_ndvi
# }
# 
# # 2. Create regional mosaic
# great_lakes_mosaic <- create_raster_mosaic(
#   input_data = regional_ndvi,
#   method = "merge",
#   region_boundary = "Great Lakes Region"
# )
# 
# # 3. Regional statistics
# regional_stats <- terra::global(great_lakes_mosaic,
#                                c("mean", "sd", "min", "max"),
#                                na.rm = TRUE)
# 
# # 4. State-by-state comparison
# state_means <- sapply(regional_ndvi, function(x) {
#   terra::global(x, "mean", na.rm = TRUE)[[1]]
# })
# 
# names(state_means) <- great_lakes_states
# print(sort(state_means, decreasing = TRUE))

## ----eval=FALSE---------------------------------------------------------------
# # If auto-detection fails, specify band names manually
# custom_ndvi <- calculate_vegetation_index(
#   spectral_data = "unusual_satellite_data.tif",
#   band_names = c("Band_4_Red", "Band_5_NIR"),  # Custom names
#   index_type = "NDVI",
#   auto_detect_bands = FALSE
# )
# 
# # Or use individual band approach
# manual_ndvi <- calculate_vegetation_index(
#   red = satellite_data$Band_4_Red,
#   nir = satellite_data$Band_5_NIR,
#   index_type = "NDVI"
# )

## ----eval=FALSE---------------------------------------------------------------
# # Automatic CRS fixing
# robust_indices <- calculate_multiple_indices(
#   red = "red_utm.tif",        # UTM projection
#   nir = "nir_geographic.tif", # Geographic coordinates
#   indices = c("NDVI", "EVI"),
#   auto_crs_fix = TRUE,        # Automatically handle CRS differences
#   verbose = TRUE              # See what's being fixed
# )

## ----eval=FALSE---------------------------------------------------------------
# # Process large areas efficiently
# # 1. Use chunked processing
# large_area_ndvi <- calculate_vegetation_index(
#   spectral_data = "very_large_raster.tif",
#   index_type = "NDVI",
#   chunk_size = 500000,    # Smaller chunks
#   auto_detect_bands = TRUE
# )
# 
# # 2. Process by regions
# us_states <- c("Ohio", "Michigan", "Indiana")
# state_results <- list()
# 
# for (state in us_states) {
#   state_results[[state]] <- calculate_vegetation_index(
#     spectral_data = "continental_satellite_data.tif",
#     index_type = "NDVI",
#     region_boundary = state,     # Process each state separately
#     auto_detect_bands = TRUE
#   )
# }
# 
# # 3. Combine results
# combined_results <- create_raster_mosaic(state_results, method = "merge")

## ----eval=FALSE---------------------------------------------------------------
# # Efficient workflow
# optimized_workflow <- function(satellite_data, study_region) {
#   # 1. Crop to region first (reduces data size)
#   cropped_data <- universal_spatial_join(
#     source_data = satellite_data,
#     target_data = get_region_boundary(study_region),
#     method = "crop"
#   )
# 
#   # 2. Calculate multiple indices in one call
#   vegetation_indices <- calculate_multiple_indices(
#     spectral_data = cropped_data,
#     indices = c("NDVI", "EVI", "SAVI", "GNDVI"),
#     auto_detect_bands = TRUE,
#     output_stack = TRUE,
#     parallel = FALSE  # Use FALSE for stability
#   )
# 
#   # 3. Cache results
#   terra::writeRaster(vegetation_indices, "cached_vegetation_indices.tif")
# 
#   return(vegetation_indices)
# }

## ----eval=FALSE---------------------------------------------------------------
# # Custom ratio index
# custom_ratio <- nir_band / red_band
# names(custom_ratio) <- "Custom_Ratio"
# 
# # Custom normalized difference
# custom_nd <- (nir_band - green_band) / (nir_band + green_band)
# names(custom_nd) <- "Custom_ND"
# 
# # Combine with standard indices
# all_indices <- c(
#   calculate_vegetation_index(red = red, nir = nir, index_type = "NDVI"),
#   custom_ratio,
#   custom_nd
# )

## ----eval=FALSE---------------------------------------------------------------
# # Combine vegetation indices with environmental data
# environmental_analysis <- universal_spatial_join(
#   source_data = vegetation_indices,
#   target_data = list(
#     precipitation = "annual_precip.tif",
#     temperature = "mean_temp.tif",
#     elevation = "dem.tif"
#   ),
#   method = "extract"
# )
# 
# # Analyze relationships
# vegetation_env_correlation <- analyze_variable_correlations(
#   variable_list = list(
#     NDVI = vegetation_indices$NDVI,
#     precipitation = environmental_data$precipitation,
#     temperature = environmental_data$temperature
#   ),
#   create_plots = TRUE
# )

## ----eval=FALSE---------------------------------------------------------------
# # Explore more indices
# list_vegetation_indices(detailed = TRUE)
# 
# # Get help
# ?calculate_vegetation_index
# ?calculate_multiple_indices
# ?analyze_crop_vegetation
# 
# # Test your installation
# test_geospatialsuite_package_simple(verbose = TRUE)

## ----eval=FALSE---------------------------------------------------------------
# # All of these will be recognized as the red band
# calculate_vegetation_index(red = red_band, nir = nir_band, index_type = "NDVI")
# calculate_vegetation_index(spectral_data = raster_with_band_named_"B4", auto_detect_bands = TRUE)
# calculate_vegetation_index(spectral_data = raster_with_band_named_"RED", auto_detect_bands = TRUE)

## ----eval=FALSE---------------------------------------------------------------
# library(geospatialsuite)
# library(terra)
# 
# # If your Landsat file has band names: B1, B2, B3, B4, B5, B6, B7
# landsat <- rast("LC08_L2SP_029030_20230615_B1-7.tif")
# 
# # Auto-detection will work automatically
# ndvi <- calculate_vegetation_index(
#   spectral_data = landsat,
#   index_type = "NDVI",
#   auto_detect_bands = TRUE
# )
# 
# # Or specify bands explicitly
# ndvi <- calculate_vegetation_index(
#   red = landsat[["B4"]],
#   nir = landsat[["B5"]],
#   index_type = "NDVI"
# )

## ----eval=FALSE---------------------------------------------------------------
# # If your Sentinel-2 file has standard band names
# sentinel <- rast("S2A_MSIL2A_20230615_B02-B12.tif")
# 
# # Auto-detection works
# ndvi <- calculate_vegetation_index(
#   spectral_data = sentinel,
#   index_type = "NDVI",
#   auto_detect_bands = TRUE
# )
# 
# # Calculate red edge index (requires Sentinel-2)
# ndre <- calculate_vegetation_index(
#   spectral_data = sentinel,
#   index_type = "NDRE",
#   auto_detect_bands = TRUE
# )
# 
# # Or use specific band names
# evi <- calculate_vegetation_index(
#   red = sentinel[["B04"]],
#   nir = sentinel[["B08"]],
#   blue = sentinel[["B02"]],
#   index_type = "EVI"
# )

## ----eval=FALSE---------------------------------------------------------------
# modis <- rast("MOD13Q1_NDVI_2023165.tif")
# 
# # If bands are named generically
# ndvi <- calculate_vegetation_index(
#   spectral_data = modis,
#   index_type = "NDVI",
#   auto_detect_bands = TRUE
# )

## ----eval=FALSE---------------------------------------------------------------
# # Your raster has bands: "band_A", "band_B", "band_C", "band_D"
# my_raster <- rast("custom_satellite.tif")
# 
# # Rename to standard names
# names(my_raster) <- c("red", "green", "blue", "nir")
# 
# # Now auto-detection works
# ndvi <- calculate_vegetation_index(
#   spectral_data = my_raster,
#   index_type = "NDVI",
#   auto_detect_bands = TRUE
# )

## ----eval=FALSE---------------------------------------------------------------
# # Tell the function which bands are which
# ndvi <- calculate_vegetation_index(
#   spectral_data = my_raster,
#   band_names = c("band_A", "band_B", "band_C", "band_D"),  # Order: Red, Green, Blue, NIR
#   index_type = "NDVI",
#   auto_detect_bands = FALSE
# )

## ----eval=FALSE---------------------------------------------------------------
# # Extract specific layers
# red_band <- my_raster[[1]]   # Assuming layer 1 is red
# nir_band <- my_raster[[4]]   # Assuming layer 4 is NIR
# 
# # Pass explicitly
# ndvi <- calculate_vegetation_index(
#   red = red_band,
#   nir = nir_band,
#   index_type = "NDVI"
# )

## ----eval=FALSE---------------------------------------------------------------
# # Check your band names
# names(my_raster)
# # [1] "sr_band_4" "sr_band_5" "sr_band_3" "sr_band_2"
# 
# # Rename them
# names(my_raster) <- c("red", "nir", "green", "blue")
# 
# # Or extract and pass explicitly
# calculate_vegetation_index(
#   red = my_raster[[1]],
#   nir = my_raster[[2]],
#   index_type = "NDVI"
# )

## ----eval=FALSE---------------------------------------------------------------
# # Don't use auto-detection, be explicit
# calculate_vegetation_index(
#   red = my_raster[["B04"]],
#   nir = my_raster[["B08"]],
#   red_edge = my_raster[["B05"]],
#   index_type = "NDRE"
# )

## ----eval=FALSE---------------------------------------------------------------
# # Create file list
# band_files <- c(
#   red = "LC08_B4.tif",
#   nir = "LC08_B5.tif",
#   blue = "LC08_B2.tif"
# )
# 
# # Let the function load them
# evi <- calculate_vegetation_index(
#   spectral_data = band_files,
#   index_type = "EVI"
# )

## ----eval=FALSE---------------------------------------------------------------
# # If all bands are in one directory with recognizable names
# ndvi <- calculate_vegetation_index(
#   spectral_data = "/path/to/landsat/bands/",
#   index_type = "NDVI",
#   auto_detect_bands = TRUE
# )

## ----eval=FALSE---------------------------------------------------------------
# # Turn on verbose mode
# result <- calculate_vegetation_index(
#   spectral_data = my_raster,
#   index_type = "NDVI",
#   auto_detect_bands = TRUE,
#   verbose = TRUE  # This will print which bands were detected
# )

Try the geospatialsuite package in your browser

Any scripts or data that you put into this service are public.

geospatialsuite documentation built on Nov. 6, 2025, 1:06 a.m.