R/12-workflows.R

Defines functions run_enhanced_mosaic_workflow run_enhanced_temporal_workflow run_enhanced_water_quality_workflow run_enhanced_terrain_analysis_workflow generate_html_summary generate_enhanced_analysis_summary calculate_comprehensive_vegetation_stats run_interactive_mapping_workflow run_enhanced_water_quality_workflow run_comprehensive_vegetation_workflow run_enhanced_ndvi_crop_workflow run_comprehensive_geospatial_workflow

Documented in calculate_comprehensive_vegetation_stats generate_enhanced_analysis_summary generate_html_summary run_comprehensive_geospatial_workflow run_comprehensive_vegetation_workflow run_enhanced_mosaic_workflow run_enhanced_ndvi_crop_workflow run_enhanced_temporal_workflow run_enhanced_terrain_analysis_workflow run_enhanced_water_quality_workflow run_interactive_mapping_workflow

#' Run comprehensive geospatial workflow -
#'
#' @description
#' Execute complete geospatial analysis workflows with simplified visualization.
#'  to handle test cases and provide robust error handling without complex dependencies.
#'
#' @param analysis_config List containing analysis configuration with required fields:
#'   \itemize{
#'     \item analysis_type: "ndvi_crop_analysis", "water_quality_analysis",
#'                         "terrain_analysis", "temporal_analysis", "vegetation_comprehensive",
#'                         "mosaic_analysis", "interactive_mapping"
#'     \item input_data: Input data paths or objects
#'     \item region_boundary: Region boundary specification
#'     \item output_folder: Output directory (optional)
#'     \item visualization_config: Visualization settings (optional)
#'   }
#'
#' @return List containing analysis results, visualizations, summary, and configuration
#'
#' @examples
#' \dontrun{
#' # These examples require external data files not included with the package
#' # Simple NDVI crop analysis workflow
#' config <- list(
#'   analysis_type = "ndvi_crop_analysis",
#'   input_data = list(red = red_raster, nir = nir_raster),
#'   region_boundary = "Ohio",
#'   output_folder = "results/"
#' )
#' results <- run_comprehensive_geospatial_workflow(config)
#' }
#'
#' @export
run_comprehensive_geospatial_workflow <- function(analysis_config) {

  message("Starting comprehensive geospatial workflow with simplified visualization...")

  # Validate configuration - IMPROVED
  required_fields <- c("analysis_type", "input_data")
  missing_fields <- setdiff(required_fields, names(analysis_config))
  if (length(missing_fields) > 0) {
    stop(paste("Missing required configuration fields:", paste(missing_fields, collapse = ", ")), call. = FALSE)
  }

  # Extract configuration with defaults
  analysis_type <- analysis_config$analysis_type
  input_data <- analysis_config$input_data
  region_boundary <- analysis_config$region_boundary
  output_folder <- analysis_config$output_folder %||% tempdir()
  viz_config <- analysis_config$visualization_config %||% list(create_maps = TRUE)

  # Create output folder - IMPROVED
  tryCatch({
    if (!dir.exists(output_folder)) {
      dir.create(output_folder, recursive = TRUE)
    }
  }, error = function(e) {
    warning(sprintf("Could not create output folder: %s. Using temp directory.", e$message))
    output_folder <<- tempdir()
  })

  # Execute workflow based on analysis type - IMPROVED ERROR HANDLING
  results <- tryCatch({
    switch(analysis_type,

           "ndvi_crop_analysis" = {
             # Enhanced NDVI analysis
             run_enhanced_ndvi_crop_workflow(analysis_config, output_folder)
           },

           "vegetation_comprehensive" = {
             # Comprehensive vegetation analysis
             run_comprehensive_vegetation_workflow(analysis_config, output_folder)
           },

           "water_quality_analysis" = {
             # Enhanced water quality analysis
             run_enhanced_water_quality_workflow(analysis_config, output_folder)
           },

           "terrain_analysis" = {
             # Advanced terrain analysis
             run_enhanced_terrain_analysis_workflow(analysis_config, output_folder)
           },

           "temporal_analysis" = {
             # Temporal change analysis
             run_enhanced_temporal_workflow(analysis_config, output_folder)
           },

           "interactive_mapping" = {
             # Interactive mapping workflow
             run_interactive_mapping_workflow(analysis_config, output_folder)
           },

           "mosaic_analysis" = {
             # Enhanced raster mosaicing
             run_enhanced_mosaic_workflow(analysis_config, output_folder)
           },

           "multi_dataset_integration" = {
             # Multi-dataset spatial integration
             run_multi_dataset_workflow(analysis_config, output_folder)
           },

           # Default case
           {
             warning(paste("Unsupported analysis type:", analysis_type, ". Running basic analysis."))
             list(
               analysis_type = analysis_type,
               message = "Basic analysis completed (unsupported type)",
               input_data = input_data
             )
           }
    )
  }, error = function(e) {
    error_result <- list(
      analysis_type = analysis_type,
      error = TRUE,
      error_message = e$message,
      message = paste("Workflow failed:", e$message)
    )
    warning(sprintf("Workflow failed: %s", e$message))
    return(error_result)
  })

  # Generate summary report
  summary_report <- generate_enhanced_analysis_summary(results, analysis_config)

  # Save summary text file
  summary_file <- file.path(output_folder, "analysis_summary.txt")
  tryCatch({
    writeLines(summary_report, summary_file)
  }, error = function(e) {
    warning("Could not save summary file")
  })

  message("Comprehensive workflow completed!")
  message(sprintf("Results saved to: %s", output_folder))

  return(list(
    results = results,
    summary = summary_report,
    output_folder = output_folder,
    config = analysis_config,
    visualizations = results$visualizations %||% list()
  ))
}

#' Run enhanced NDVI crop analysis workflow -
#'
#' @description
#' Enhanced NDVI workflow with quality filtering, temporal analysis, and visualization.
#'  to handle test scenarios and provide robust error handling.
#'
#' @param config Analysis configuration
#' @param output_folder Output directory
#'
#' @return List with enhanced NDVI results and visualizations
#'
#' @export
run_enhanced_ndvi_crop_workflow <- function(config, output_folder = tempdir()) {

  message("Starting enhanced NDVI crop analysis workflow...")

  # Extract configuration with error handling
  red_data <- config$red_data %||% config$input_data$red %||% config$input_data
  nir_data <- config$nir_data %||% config$input_data$nir %||% config$input_data
  region_boundary <- config$region_boundary
  cdl_data <- config$cdl_data
  crop_codes <- config$crop_codes
  indices <- config$indices %||% c("NDVI", "EVI", "SAVI")
  viz_config <- config$visualization_config %||% list()

  # Handle case where input_data is a single raster with multiple bands
  if (inherits(config$input_data, "SpatRaster") && is.null(red_data)) {
    if (terra::nlyr(config$input_data) >= 2) {
      red_data <- config$input_data[[1]]
      nir_data <- config$input_data[[2]]
      if (config$verbose %||% FALSE) message("Using first two bands as red and NIR")
    } else {
      stop("Input raster must have at least 2 bands for NDVI calculation")
    }
  }

  # Step 1: Enhanced NDVI calculation with error handling
  message("Step 1: Calculating enhanced NDVI...")
  ndvi_result <- tryCatch({
    calculate_ndvi_enhanced(
      red_data = red_data,
      nir_data = nir_data,
      match_by_date = config$match_by_date %||% FALSE,
      quality_filter = config$quality_filter %||% FALSE,
      temporal_smoothing = config$temporal_smoothing %||% FALSE,
      verbose = TRUE
    )
  }, error = function(e) {
    warning(sprintf("Enhanced NDVI calculation failed: %s", e$message))
    # Fallback: try simple NDVI calculation
    if (inherits(red_data, "SpatRaster") && inherits(nir_data, "SpatRaster")) {
      simple_ndvi <- (nir_data - red_data) / (nir_data + red_data)
      names(simple_ndvi) <- "NDVI_fallback"
      return(simple_ndvi)
    } else {
      stop("Cannot calculate NDVI with provided data")
    }
  })

  # Step 2: Calculate additional vegetation indices if requested
  message("Step 2: Calculating additional vegetation indices...")
  vegetation_stack <- ndvi_result

  if (length(indices) > 1 && inherits(red_data, "SpatRaster") && inherits(nir_data, "SpatRaster")) {
    tryCatch({
      additional_indices <- calculate_multiple_indices(
        red = red_data,
        nir = nir_data,
        indices = setdiff(indices, "NDVI")[1:min(2, length(setdiff(indices, "NDVI")))], # Limit for reliability
        output_stack = TRUE,
        region_boundary = region_boundary,
        verbose = FALSE
      )

      # Combine if dimensions match
      if (terra::nlyr(ndvi_result) == terra::nlyr(additional_indices) ||
          (terra::nlyr(ndvi_result) == 1 && terra::nlyr(additional_indices) >= 1)) {
        vegetation_stack <- c(ndvi_result, additional_indices[[1]])
      }
    }, error = function(e) {
      message("Additional indices calculation failed, using NDVI only")
    })
  }

  # Step 3: Apply region boundary
  if (!is.null(region_boundary)) {
    message("Step 3: Applying region boundary...")
    tryCatch({
      boundary <- get_region_boundary(region_boundary)
      boundary_vect <- terra::vect(boundary)
      vegetation_stack <- terra::crop(vegetation_stack, boundary_vect)
      vegetation_stack <- terra::mask(vegetation_stack, boundary_vect)
    }, error = function(e) {
      warning(sprintf("Failed to apply region boundary: %s", e$message))
    })
  }

  # Step 4: Apply crop mask if provided
  crop_mask <- NULL
  if (!is.null(cdl_data) && !is.null(crop_codes)) {
    message("Step 4: Creating and applying crop mask...")
    tryCatch({
      crop_mask <- create_crop_mask(cdl_data, crop_codes, region_boundary)
      vegetation_stack <- terra::mask(vegetation_stack, crop_mask)
    }, error = function(e) {
      warning(sprintf("Failed to apply crop mask: %s", e$message))
    })
  }

  # Step 5: Simplified visualization
  message("Step 5: Creating visualizations...")
  visualizations <- list()

  # NDVI map using terra plotting
  if (viz_config$create_maps %||% TRUE) {
    tryCatch({
      if (!is.null(viz_config$output_file)) {
        output_file <- file.path(output_folder, "ndvi_map.png")
      } else {
        output_file <- NULL
      }

      visualizations$ndvi_map <- create_ndvi_map(
        ndvi_data = vegetation_stack[[1]],
        region_boundary = region_boundary,
        ndvi_classes = viz_config$ndvi_classes %||% "none",
        title = "NDVI Analysis",
        output_file = output_file
      )
    }, error = function(e) {
      warning(sprintf("NDVI map creation failed: %s", e$message))
    })
  }

  # Interactive map if requested and leaflet available
  if (viz_config$interactive %||% FALSE) {
    tryCatch({
      if (requireNamespace("leaflet", quietly = TRUE)) {
        # Convert raster to points for leaflet
        raster_points <- terra::as.points(vegetation_stack[[1]])
        points_sf <- sf::st_as_sf(raster_points)

        visualizations$interactive_map <- create_interactive_map(
          spatial_data = points_sf,
          fill_variable = names(vegetation_stack)[1],
          title = "Interactive NDVI Map"
        )

        # Save interactive map
        if (requireNamespace("htmlwidgets", quietly = TRUE)) {
          htmlwidgets::saveWidget(
            visualizations$interactive_map,
            file.path(output_folder, "interactive_ndvi_map.html")
          )
        }
      }
    }, error = function(e) {
      warning(sprintf("Interactive map creation failed: %s", e$message))
    })
  }

  # Crop distribution map if CDL data available
  if (!is.null(crop_mask)) {
    tryCatch({
      visualizations$crop_map <- create_crop_map(
        cdl_data = cdl_data,
        crop_selection = crop_codes,
        region_boundary = region_boundary,
        style = "categorical",
        output_file = file.path(output_folder, "crop_distribution.png")
      )
    }, error = function(e) {
      warning(sprintf("Crop map creation failed: %s", e$message))
    })
  }

  # Step 6: Save raster results
  message("Step 6: Saving raster results...")
  output_files <- list()

  tryCatch({
    # Save vegetation indices stack
    vegetation_file <- file.path(output_folder, "vegetation_indices.tif")
    terra::writeRaster(vegetation_stack, vegetation_file, overwrite = TRUE)
    output_files$vegetation_indices <- vegetation_file

    # Save crop mask if created
    if (!is.null(crop_mask)) {
      mask_file <- file.path(output_folder, "crop_mask.tif")
      terra::writeRaster(crop_mask, mask_file, overwrite = TRUE)
      output_files$crop_mask <- mask_file
    }
  }, error = function(e) {
    warning(sprintf("Failed to save raster results: %s", e$message))
  })

  # Step 7: Generate statistics
  message("Step 7: Generating statistics...")
  vegetation_stats <- tryCatch({
    calculate_comprehensive_vegetation_stats(vegetation_stack, names(vegetation_stack))
  }, error = function(e) {
    list(error = paste("Statistics calculation failed:", e$message))
  })

  message("Enhanced NDVI crop workflow completed successfully!")

  return(list(
    vegetation_data = vegetation_stack,
    crop_mask = crop_mask,
    statistics = vegetation_stats,
    visualizations = visualizations,
    output_files = output_files
  ))
}

#' Run comprehensive vegetation analysis workflow -
#'
#' @description
#' Complete vegetation analysis using multiple indices with simplified processing.
#'  for reliability and test compatibility.
#'
#' @param config Analysis configuration
#' @param output_folder Output directory
#'
#' @return Comprehensive vegetation analysis results
#'
#' @export
run_comprehensive_vegetation_workflow <- function(config, output_folder = tempdir()) {

  message("Starting comprehensive vegetation analysis workflow...")

  # Extract configuration
  spectral_data <- config$input_data
  region_boundary <- config$region_boundary
  indices <- config$indices %||% c("NDVI", "EVI", "SAVI")
  crop_type <- config$crop_type %||% "general"
  analysis_type <- config$analysis_type_detail %||% "comprehensive"

  # Step 1: Comprehensive vegetation analysis
  message("Step 1: Performing comprehensive vegetation analysis...")
  vegetation_analysis <- tryCatch({
    analyze_crop_vegetation(
      spectral_data = spectral_data,
      crop_type = crop_type,
      analysis_type = analysis_type,
      cdl_mask = config$cdl_mask,
      output_folder = output_folder,
      verbose = TRUE
    )
  }, error = function(e) {
    warning(sprintf("Comprehensive vegetation analysis failed: %s", e$message))
    # Fallback analysis
    list(
      vegetation_indices = if (inherits(spectral_data, "SpatRaster")) spectral_data else NULL,
      analysis_results = list(error = e$message),
      metadata = list(crop_type = crop_type, analysis_type = analysis_type)
    )
  })

  # Step 2: Calculate additional indices for comparison
  message("Step 2: Calculating multiple vegetation indices...")
  multiple_indices <- tryCatch({
    if (inherits(spectral_data, "SpatRaster") && terra::nlyr(spectral_data) >= 2) {
      calculate_multiple_indices(
        red = spectral_data[[1]],
        nir = spectral_data[[if(terra::nlyr(spectral_data) >= 4) 4 else 2]],
        blue = if(terra::nlyr(spectral_data) >= 3) spectral_data[[3]] else NULL,
        green = if(terra::nlyr(spectral_data) >= 2) spectral_data[[2]] else NULL,
        indices = indices[1:min(3, length(indices))], # Limit for reliability
        output_stack = TRUE,
        region_boundary = region_boundary,
        parallel = FALSE, # Disable parallel for stability
        verbose = FALSE
      )
    } else {
      vegetation_analysis$vegetation_indices
    }
  }, error = function(e) {
    warning(sprintf("Multiple indices calculation failed: %s", e$message))
    vegetation_analysis$vegetation_indices
  })

  # Step 3: Simplified visualization
  message("Step 3: Creating visualizations...")
  visualizations <- list()

  # Create individual index maps using terra plotting
  if (!is.null(multiple_indices) && inherits(multiple_indices, "SpatRaster")) {
    for (i in 1:min(3, terra::nlyr(multiple_indices))) {
      idx_name <- names(multiple_indices)[i]
      tryCatch({
        viz_file <- file.path(output_folder, paste0(idx_name, "_map.png"))

        # Use terra plotting and save
        png(viz_file, width = 1200, height = 800, res = 300)
        colors <- get_terra_colors(if (idx_name == "NDVI") "ndvi" else "viridis")
        terra::plot(multiple_indices[[i]], main = paste(idx_name, "Analysis"), col = colors)
        dev.off()

        visualizations[[paste0(idx_name, "_map")]] <- viz_file
        message(sprintf("  Created %s map", idx_name))
      }, error = function(e) {
        warning(sprintf("Failed to create %s map: %s", idx_name, e$message))
      })
    }
  }

  # Step 4: Save results
  message("Step 4: Saving results...")
  output_files <- list()

  tryCatch({
    # Save multi-index stack
    if (!is.null(multiple_indices)) {
      indices_file <- file.path(output_folder, "vegetation_indices_stack.tif")
      terra::writeRaster(multiple_indices, indices_file, overwrite = TRUE)
      output_files$indices_stack <- indices_file
    }

    # Save analysis results
    analysis_file <- file.path(output_folder, "vegetation_analysis.rds")
    saveRDS(vegetation_analysis, analysis_file)
    output_files$analysis_results <- analysis_file
  }, error = function(e) {
    warning(sprintf("Failed to save results: %s", e$message))
  })

  message("Comprehensive vegetation workflow completed successfully!")

  return(list(
    vegetation_analysis = vegetation_analysis,
    indices_stack = multiple_indices,
    visualizations = visualizations,
    statistics = vegetation_analysis$analysis_results$summary_statistics %||% list(),
    output_files = output_files
  ))
}

#' Run enhanced water quality analysis workflow
#'
#' @description
#' Enhanced water quality workflow with simplified visualization.
#'
#' @param config Analysis configuration
#' @param output_folder Output directory
#'
#' @return Enhanced water quality analysis results
#'
#' @export
run_enhanced_water_quality_workflow <- function(config, output_folder = tempdir()) {

  message("Starting enhanced water quality analysis workflow...")

  # Extract configuration
  water_data <- config$input_data
  variable <- config$variable %||% "discharge"
  region_boundary <- config$region_boundary
  river_network <- config$river_network
  thresholds <- config$thresholds

  # Step 1: Water quality analysis
  message("Step 1: Performing water quality analysis...")
  water_analysis <- tryCatch({
    analyze_water_quality_comprehensive(
      water_data = water_data,
      variable = variable,
      region_boundary = region_boundary,
      river_network = river_network,
      output_folder = output_folder,
      thresholds = thresholds
    )
  }, error = function(e) {
    warning(sprintf("Water quality analysis failed: %s", e$message))
    list(
      water_data = water_data,
      statistics = list(error = e$message),
      message = paste("Water quality analysis failed:", e$message)
    )
  })

  # Step 2: Enhanced visualization
  message("Step 2: Creating water quality visualizations...")
  visualizations <- list()

  # Interactive water quality map if leaflet available
  if (requireNamespace("leaflet", quietly = TRUE) && !is.null(water_analysis$water_data)) {
    tryCatch({
      visualizations$interactive_map <- create_interactive_map(
        spatial_data = water_analysis$water_data,
        fill_variable = variable,
        basemap = "terrain",
        title = paste("Water Quality:", stringr::str_to_title(variable))
      )

      # Save interactive map
      if (requireNamespace("htmlwidgets", quietly = TRUE)) {
        htmlwidgets::saveWidget(
          visualizations$interactive_map,
          file.path(output_folder, "interactive_water_quality.html")
        )
      }
    }, error = function(e) {
      warning(sprintf("Interactive map creation failed: %s", e$message))
    })
  }

  # Static water quality plot
  tryCatch({
    visualizations$quality_plot <- create_water_quality_plot(
      water_data = water_analysis$water_data,
      variable = variable,
      region_boundary = region_boundary,
      river_network = river_network,
      thresholds = thresholds,
      output_file = file.path(output_folder, "water_quality_plot.png")
    )
  }, error = function(e) {
    warning(sprintf("Water quality plot creation failed: %s", e$message))
  })

  message("Enhanced water quality workflow completed successfully!")

  return(list(
    water_analysis = water_analysis,
    visualizations = visualizations,
    statistics = water_analysis$statistics,
    output_files = list(
      interactive_map = file.path(output_folder, "interactive_water_quality.html"),
      quality_plot = file.path(output_folder, "water_quality_plot.png")
    )
  ))
}

#' Run interactive mapping workflow
#'
#' @description
#' Create interactive mapping workflow with multiple data types and layers.
#' Simplified for reliability.
#'
#' @param config Analysis configuration
#' @param output_folder Output directory
#'
#' @return Interactive mapping results
#'
#' @export
run_interactive_mapping_workflow <- function(config, output_folder = tempdir()) {

  message("Starting interactive mapping workflow...")

  # Extract configuration
  data_layers <- config$input_data
  region_boundary <- config$region_boundary
  basemap <- config$basemap %||% "terrain"

  # Handle single data layer case
  if (!is.list(data_layers)) {
    data_layers <- list(main_data = data_layers)
  }

  # Create interactive maps for each data layer
  interactive_maps <- list()

  for (layer_name in names(data_layers)) {
    message(sprintf("Creating interactive map for: %s", layer_name))

    tryCatch({
      # Process the data layer
      layer_data <- data_layers[[layer_name]]

      if (inherits(layer_data, "SpatRaster")) {
        # Convert raster to points for leaflet
        if (requireNamespace("leaflet", quietly = TRUE)) {
          raster_points <- terra::as.points(layer_data)
          points_sf <- sf::st_as_sf(raster_points)

          interactive_maps[[layer_name]] <- create_interactive_map(
            spatial_data = points_sf,
            basemap = basemap,
            title = stringr::str_to_title(gsub("_", " ", layer_name))
          )
        }
      } else {
        # Vector data
        interactive_maps[[layer_name]] <- create_interactive_map(
          spatial_data = layer_data,
          basemap = basemap,
          title = stringr::str_to_title(gsub("_", " ", layer_name))
        )
      }

      # Save individual maps
      if (requireNamespace("htmlwidgets", quietly = TRUE)) {
        map_file <- file.path(output_folder, paste0("interactive_", layer_name, ".html"))
        htmlwidgets::saveWidget(interactive_maps[[layer_name]], map_file)
      }
    }, error = function(e) {
      warning(sprintf("Failed to create interactive map for %s: %s", layer_name, e$message))
    })
  }

  message("Interactive mapping workflow completed successfully!")

  return(list(
    interactive_maps = interactive_maps,
    output_files = list(
      maps_directory = output_folder
    )
  ))
}

# ==================== HELPER FUNCTIONS ==================== #

#' Calculate comprehensive vegetation statistics -
#' @keywords internal
calculate_comprehensive_vegetation_stats <- function(vegetation_stack, indices) {

  if (is.null(vegetation_stack) || !inherits(vegetation_stack, "SpatRaster")) {
    return(list(error = "Invalid vegetation stack"))
  }

  stats <- list()

  for (i in 1:min(terra::nlyr(vegetation_stack), length(indices))) {
    layer_name <- if (i <= length(indices)) indices[i] else names(vegetation_stack)[i]

    tryCatch({
      values <- terra::values(vegetation_stack[[i]], mat = FALSE)
      values <- values[!is.na(values)]

      if (length(values) > 0) {
        stats[[layer_name]] <- list(
          mean = mean(values),
          median = median(values),
          sd = sd(values),
          min = min(values),
          max = max(values),
          range = max(values) - min(values),
          cv = sd(values) / mean(values),
          percentiles = quantile(values, c(0.05, 0.25, 0.75, 0.95)),
          n_valid = length(values),
          coverage_percent = (length(values) / terra::ncell(vegetation_stack[[i]])) * 100
        )
      }
    }, error = function(e) {
      stats[[layer_name]] <<- list(error = paste("Statistics calculation failed:", e$message))
    })
  }

  return(stats)
}

#' Generate enhanced analysis summary
#' @keywords internal
generate_enhanced_analysis_summary <- function(results, config) {

  summary_lines <- c(
    "GEOSPATIALSUITE ANALYSIS SUMMARY",
    "=================================",
    "",
    paste("Analysis Type:", config$analysis_type),
    paste("Date:", Sys.time()),
    paste("Region:", if(is.character(config$region_boundary)) config$region_boundary else "Custom boundary"),
    paste("GeoSpatialSuite Version: 0.1.0"),
    "",
    "RESULTS OVERVIEW:",
    "----------------"
  )

  # Add results information
  if (!is.null(results$error)) {
    summary_lines <- c(summary_lines, paste("ERROR:", results$error_message))
  } else {
    summary_lines <- c(summary_lines, "Analysis completed successfully")

    if (!is.null(results$vegetation_data)) {
      n_layers <- if (inherits(results$vegetation_data, "SpatRaster")) terra::nlyr(results$vegetation_data) else 1
      summary_lines <- c(summary_lines, paste("Vegetation layers created:", n_layers))
    }

    if (!is.null(results$visualizations)) {
      summary_lines <- c(summary_lines, paste("Visualizations created:", length(results$visualizations)))
    }
  }

  summary_lines <- c(summary_lines,
                     "",
                     "TECHNICAL NOTES:",
                     "- Uses standard terra plotting for reliability",
                     "- Simplified workflows for stability",
                     "- No complex dependencies required",
                     "",
                     "Analysis completed with GeoSpatialSuite!"
  )

  return(summary_lines)
}

#' Generate HTML summary report
#' @keywords internal
generate_html_summary <- function(summary_report, results, output_file) {

  # Create basic HTML summary
  html_content <- c(
    "<!DOCTYPE html>",
    "<html><head><title>GeoSpatialSuite Analysis Summary</title></head>",
    "<body>",
    "<h1>GeoSpatialSuite Analysis Summary</h1>",
    paste0("<p>", summary_report, "</p>"),
    "</body></html>"
  )

  writeLines(html_content, output_file)
}







#' Run enhanced terrain analysis workflow
#' @keywords internal
run_enhanced_terrain_analysis_workflow <- function(config, output_folder = tempdir()) {
  message("Starting enhanced terrain analysis workflow...")

  # Extract configuration
  elevation_data <- config$input_data$elevation %||% config$input_data
  region_boundary <- config$region_boundary
  terrain_vars <- config$terrain_vars %||% c("slope", "aspect", "TRI", "TPI")

  # Load elevation data
  if (is.character(elevation_data)) {
    elevation_raster <- terra::rast(elevation_data)
  } else {
    elevation_raster <- config$input_data
  }

  # Apply region boundary if provided
  if (!is.null(region_boundary)) {
    tryCatch({
      boundary <- get_region_boundary(region_boundary)
      boundary_vect <- terra::vect(boundary)
      elevation_raster <- terra::crop(elevation_raster, boundary_vect)
      elevation_raster <- terra::mask(elevation_raster, boundary_vect)
    }, error = function(e) {
      warning(sprintf("Failed to apply region boundary: %s", e$message))
    })
  }

  # Calculate terrain variables
  terrain_results <- list()

  for (var in terrain_vars) {
    message(sprintf("Calculating %s...", var))
    tryCatch({
      terrain_raster <- switch(var,
                               "slope" = terra::terrain(elevation_raster, opt = "slope", unit = "degrees"),
                               "aspect" = terra::terrain(elevation_raster, opt = "aspect", unit = "degrees"),
                               "TRI" = terra::terrain(elevation_raster, opt = "TRI"),
                               "TPI" = terra::terrain(elevation_raster, opt = "TPI"),
                               "flowdir" = terra::terrain(elevation_raster, opt = "flowdir"),
                               "roughness" = terra::terrain(elevation_raster, opt = "roughness"),
                               terra::terrain(elevation_raster, opt = "slope", unit = "degrees") # default
      )
      terrain_results[[var]] <- terrain_raster
    }, error = function(e) {
      warning(sprintf("Failed to calculate %s: %s", var, e$message))
    })
  }

  # Combine results
  if (length(terrain_results) > 0) {
    terrain_stack <- terra::rast(terrain_results)
    names(terrain_stack) <- names(terrain_results)
  } else {
    terrain_stack <- elevation_raster
    names(terrain_stack) <- "elevation"
  }

  # Save results
  tryCatch({
    output_file <- file.path(output_folder, "terrain_analysis.tif")
    terra::writeRaster(terrain_stack, output_file, overwrite = TRUE)
  }, error = function(e) {
    warning(sprintf("Failed to save terrain results: %s", e$message))
  })

  message("Enhanced terrain analysis workflow completed!")

  return(list(
    analysis_type = "terrain",
    terrain_data = terrain_stack,
    terrain_variables = names(terrain_results),
    output_file = file.path(output_folder, "terrain_analysis.tif"),
    message = "Enhanced terrain analysis completed successfully"
  ))
}

#' Run enhanced water quality analysis workflow
#' @keywords internal
run_enhanced_water_quality_workflow <- function(config, output_folder = tempdir()) {
  message("Starting enhanced water quality analysis workflow...")

  # Extract configuration
  water_data <- config$input_data
  variable <- config$variable %||% "quality"
  region_boundary <- config$region_boundary

  # Simple water quality analysis
  tryCatch({
    water_analysis <- analyze_water_quality_comprehensive(
      water_data = water_data,
      variable = variable,
      region_boundary = region_boundary,
      output_folder = output_folder,
      verbose = TRUE
    )
  }, error = function(e) {
    warning(sprintf("Water quality analysis failed: %s", e$message))
    water_analysis <- list(
      water_data = water_data,
      statistics = list(error = e$message),
      message = paste("Water quality analysis failed:", e$message)
    )
  })

  message("Enhanced water quality workflow completed!")
  return(water_analysis)
}

#' Run enhanced temporal workflow
#' @keywords internal
run_enhanced_temporal_workflow <- function(config, output_folder = tempdir()) {
  message("Starting enhanced temporal workflow...")

  # Extract configuration
  input_data <- config$input_data
  dates <- config$dates
  analysis_type <- config$analysis_type_detail %||% "trend"

  # Simple temporal analysis
  tryCatch({
    temporal_results <- analyze_temporal_changes(
      data_list = input_data,
      dates = dates,
      region_boundary = config$region_boundary,
      analysis_type = analysis_type,
      output_folder = output_folder
    )
  }, error = function(e) {
    warning(sprintf("Temporal analysis failed: %s", e$message))
    temporal_results <- list(
      analysis_type = "temporal",
      message = paste("Temporal analysis failed:", e$message),
      error = e$message
    )
  })

  message("Enhanced temporal workflow completed!")
  return(temporal_results)
}

#' Run enhanced mosaic workflow
#' @keywords internal
run_enhanced_mosaic_workflow <- function(config, output_folder = tempdir()) {
  message("Starting enhanced mosaic workflow...")

  # Extract configuration
  input_data <- config$input_data
  method <- config$method %||% "merge"
  region_boundary <- config$region_boundary

  # Create mosaic
  tryCatch({
    mosaic_result <- create_raster_mosaic(
      input_data = input_data,
      method = method,
      region_boundary = region_boundary,
      output_file = file.path(output_folder, "mosaic_result.tif")
    )

    results <- list(
      analysis_type = "mosaic",
      mosaic_data = mosaic_result,
      method = method,
      output_file = file.path(output_folder, "mosaic_result.tif"),
      message = "Enhanced mosaic workflow completed successfully"
    )
  }, error = function(e) {
    warning(sprintf("Mosaic workflow failed: %s", e$message))
    results <- list(
      analysis_type = "mosaic",
      message = paste("Mosaic workflow failed:", e$message),
      error = e$message
    )
  })

  message("Enhanced mosaic workflow completed!")
  return(results)
}

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.