The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
This vignette demonstrates comprehensive agricultural analysis capabilities including USDA CDL integration, crop monitoring, stress detection, and yield assessment workflows.
Use enhanced NDVI calculation for multi-temporal crop monitoring:
# Enhanced NDVI with quality filtering
ndvi_enhanced <- calculate_ndvi_enhanced(
red_data = red_band,
nir_data = nir_band,
quality_filter = TRUE,
temporal_smoothing = FALSE, # Single date
verbose = TRUE
)
# Visualize enhanced NDVI
create_ndvi_map(
ndvi_data = ndvi_enhanced,
title = "Enhanced NDVI with Quality Filtering",
ndvi_classes = "none"
)
print("Enhanced NDVI Analysis:")
ndvi_values <- terra::values(ndvi_enhanced, mat = FALSE)
valid_ndvi <- ndvi_values[!is.na(ndvi_values)]
print(paste("Mean NDVI:", round(mean(valid_ndvi), 3)))
print(paste("NDVI range:", paste(round(range(valid_ndvi), 3), collapse = " - ")))
Calculate multiple vegetation indices for comprehensive crop assessment:
# Calculate multiple indices relevant to agriculture
agricultural_indices <- calculate_multiple_indices(
red = red_band,
nir = nir_band,
indices = c("NDVI", "SAVI", "MSAVI", "DVI", "RVI"),
output_stack = TRUE,
verbose = TRUE
)
print("Agricultural Indices Calculated:")
print(names(agricultural_indices))
# Visualize key indices
if (terra::nlyr(agricultural_indices) >= 2) {
# NDVI visualization
create_spatial_map(
spatial_data = agricultural_indices[[1]],
title = "NDVI for Agricultural Assessment",
color_scheme = "ndvi"
)
# SAVI visualization (soil-adjusted)
if ("SAVI" %in% names(agricultural_indices)) {
plot_raster_fast(
agricultural_indices[["SAVI"]],
title = "SAVI (Soil Adjusted Vegetation Index)",
color_scheme = "viridis"
)
}
}
Assess yield potential using vegetation indices:
# Extract yield analysis if available
if (!is.null(crop_analysis$analysis_results$yield_analysis)) {
yield_results <- crop_analysis$analysis_results$yield_analysis
print("Yield Potential Analysis:")
if (!"error" %in% names(yield_results)) {
print(paste("Composite yield index:", round(yield_results$composite_yield_index, 3)))
print(paste("Yield potential class:", yield_results$yield_potential_class))
print(paste("Classification confidence:", round(yield_results$classification_confidence, 3)))
print("Index contributions to yield assessment:")
for (idx in names(yield_results$index_contributions)) {
contrib <- yield_results$index_contributions[[idx]]
print(paste(" ", idx, "- Normalized:", round(contrib$mean_normalized, 3),
"Raw mean:", round(contrib$raw_mean, 3)))
}
}
}
# Create yield potential map visualization
yield_potential_raster <- agricultural_indices[[1]] # Use NDVI as proxy
terra::values(yield_potential_raster) <- ifelse(terra::values(yield_potential_raster) > 0.6, 3,
ifelse(terra::values(yield_potential_raster) > 0.4, 2, 1))
names(yield_potential_raster) <- "Yield_Potential"
plot_raster_fast(
yield_potential_raster,
title = "Yield Potential Classification",
color_scheme = "terrain"
)
Calculate key performance indicators for agricultural monitoring:
# Calculate comprehensive vegetation statistics
if (inherits(agricultural_indices, "SpatRaster")) {
veg_stats <- list()
for (i in 1:terra::nlyr(agricultural_indices)) {
index_name <- names(agricultural_indices)[i]
values <- terra::values(agricultural_indices[[i]], mat = FALSE)
valid_values <- values[!is.na(values)]
if (length(valid_values) > 0) {
veg_stats[[index_name]] <- list(
mean = mean(valid_values),
median = median(valid_values),
sd = sd(valid_values),
cv = sd(valid_values) / mean(valid_values),
min = min(valid_values),
max = max(valid_values),
q25 = quantile(valid_values, 0.25),
q75 = quantile(valid_values, 0.75)
)
}
}
print("Crop Performance Metrics:")
for (index in names(veg_stats)) {
stats <- veg_stats[[index]]
print(paste(index, "- Mean:", round(stats$mean, 3),
"CV:", round(stats$cv, 3),
"Range:", paste(round(c(stats$min, stats$max), 3), collapse = "-")))
}
}
Analyze individual fields or management zones:
# Create sample field boundaries
field_1 <- sf::st_polygon(list(matrix(c(
-83.5, 40.0, -83.3, 40.0, -83.3, 40.2, -83.5, 40.2, -83.5, 40.0
), ncol = 2, byrow = TRUE)))
field_2 <- sf::st_polygon(list(matrix(c(
-83.3, 40.0, -83.1, 40.0, -83.1, 40.2, -83.3, 40.2, -83.3, 40.0
), ncol = 2, byrow = TRUE)))
fields_sf <- sf::st_sf(
field_id = c("Field_1", "Field_2"),
crop_type = c("Corn", "Soybeans"),
geometry = sf::st_sfc(field_1, field_2, crs = 4326)
)
# Extract vegetation statistics by field using spatial join
field_analysis <- universal_spatial_join(
source_data = agricultural_indices,
target_data = fields_sf,
method = "zonal",
summary_function = "mean",
verbose = TRUE
)
print("Field-Level Analysis Results:")
if (inherits(field_analysis, "sf")) {
print(sf::st_drop_geometry(field_analysis))
}
Support precision agriculture through spatial variability analysis:
# Calculate coefficient of variation for management zones
if (inherits(agricultural_indices, "SpatRaster") && terra::nlyr(agricultural_indices) > 0) {
# Use NDVI for variability analysis
ndvi_layer <- agricultural_indices[[1]]
# Calculate local variability using focal statistics
local_cv <- terra::focal(ndvi_layer, w = matrix(1, 3, 3),
fun = function(x) sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE))
names(local_cv) <- "Local_CV"
# Classify variability zones
variability_zones <- terra::classify(local_cv,
matrix(c(0, 0.1, 1, # Low variability
0.1, 0.2, 2, # Medium variability
0.2, 1, 3), # High variability
ncol = 3, byrow = TRUE))
names(variability_zones) <- "Variability_Zones"
# Visualize variability
plot_raster_fast(
local_cv,
title = "Spatial Variability (Coefficient of Variation)",
color_scheme = "plasma"
)
plot_raster_fast(
variability_zones,
title = "Management Zones (1=Low, 2=Medium, 3=High Variability)",
color_scheme = "categorical"
)
}
Use vegetation indices to detect crop stress and disease:
# Create stress detection workflow
stress_indices <- c("NDVI", "SAVI", "DVI")
# Calculate stress thresholds based on crop type
corn_thresholds <- list(
healthy = list(NDVI = c(0.6, 1.0), SAVI = c(0.4, 0.8)),
stressed = list(NDVI = c(0.3, 0.6), SAVI = c(0.2, 0.4)),
severely_stressed = list(NDVI = c(0.0, 0.3), SAVI = c(0.0, 0.2))
)
# Apply stress classification
if (inherits(agricultural_indices, "SpatRaster") && "NDVI" %in% names(agricultural_indices)) {
ndvi_values <- terra::values(agricultural_indices[["NDVI"]], mat = FALSE)
# Classify stress levels
stress_classification <- ifelse(ndvi_values >= 0.6, "Healthy",
ifelse(ndvi_values >= 0.3, "Moderate Stress", "Severe Stress"))
# Create stress map
stress_raster <- agricultural_indices[["NDVI"]]
stress_numeric <- ifelse(ndvi_values >= 0.6, 3,
ifelse(ndvi_values >= 0.3, 2, 1))
terra::values(stress_raster) <- stress_numeric
names(stress_raster) <- "Stress_Level"
plot_raster_fast(
stress_raster,
title = "Crop Stress Classification (1=Severe, 2=Moderate, 3=Healthy)",
color_scheme = "terrain"
)
# Calculate stress statistics
stress_table <- table(stress_classification)
stress_percent <- round(prop.table(stress_table) * 100, 1)
print("Crop Stress Distribution:")
for (level in names(stress_table)) {
print(paste(level, ":", stress_table[[level]], "pixels (", stress_percent[[level]], "%)"))
}
}
Create early warning systems for crop management:
# Define warning thresholds
warning_thresholds <- list(
drought_stress = 0.4, # NDVI below this indicates drought stress
disease_risk = 0.3, # NDVI below this indicates disease risk
optimal_growth = 0.7 # NDVI above this indicates optimal conditions
)
# Generate alerts
if (exists("ndvi_values")) {
alerts <- list()
# Calculate percentages in each category
drought_pixels <- sum(ndvi_values < warning_thresholds$drought_stress, na.rm = TRUE)
disease_pixels <- sum(ndvi_values < warning_thresholds$disease_risk, na.rm = TRUE)
optimal_pixels <- sum(ndvi_values > warning_thresholds$optimal_growth, na.rm = TRUE)
total_pixels <- sum(!is.na(ndvi_values))
alerts$drought_risk <- round((drought_pixels / total_pixels) * 100, 1)
alerts$disease_risk <- round((disease_pixels / total_pixels) * 100, 1)
alerts$optimal_conditions <- round((optimal_pixels / total_pixels) * 100, 1)
print("Agricultural Alert System:")
print(paste("Drought stress risk:", alerts$drought_risk, "% of field"))
print(paste("Disease risk:", alerts$disease_risk, "% of field"))
print(paste("Optimal conditions:", alerts$optimal_conditions, "% of field"))
# Generate recommendations
if (alerts$drought_risk > 20) {
print("RECOMMENDATION: Consider irrigation scheduling")
}
if (alerts$disease_risk > 10) {
print("RECOMMENDATION: Increase disease monitoring")
}
if (alerts$optimal_conditions > 70) {
print("STATUS: Crop conditions are generally favorable")
}
}
Track crop development throughout the growing season:
# Simulate time series data for growing season
growth_stages <- c("Planting", "V6", "V12", "R1", "R3", "R6")
ndvi_progression <- c(0.2, 0.4, 0.7, 0.8, 0.75, 0.6)
# Create time series visualization concept
seasonal_data <- data.frame(
Stage = growth_stages,
NDVI = ndvi_progression,
DOY = c(120, 150, 180, 200, 220, 260) # Day of year
)
print("Seasonal NDVI Progression:")
print(seasonal_data)
# Create conceptual growth curve
if (requireNamespace("ggplot2", quietly = TRUE)) {
library(ggplot2)
growth_plot <- ggplot(seasonal_data, aes(x = DOY, y = NDVI)) +
geom_line(color = "darkgreen", size = 1.2) +
geom_point(color = "red", size = 3) +
geom_text(aes(label = Stage), vjust = -0.5) +
labs(title = "Typical Corn NDVI Progression",
x = "Day of Year",
y = "NDVI Value") +
theme_minimal() +
ylim(0, 1)
print(growth_plot)
}
Use vegetation indices to optimize harvest timing:
# Define maturity indicators based on NDVI decline
maturity_thresholds <- list(
corn = list(
early_maturity = 0.7, # NDVI starts declining
harvest_ready = 0.5, # Optimal harvest window
post_harvest = 0.3 # Past optimal timing
),
soybeans = list(
early_maturity = 0.6,
harvest_ready = 0.4,
post_harvest = 0.25
)
)
# Calculate harvest readiness
if (exists("ndvi_values")) {
# Use corn thresholds for demonstration
thresholds <- maturity_thresholds$corn
harvest_assessment <- list(
early_maturity = sum(ndvi_values <= thresholds$early_maturity &
ndvi_values > thresholds$harvest_ready, na.rm = TRUE),
harvest_ready = sum(ndvi_values <= thresholds$harvest_ready &
ndvi_values > thresholds$post_harvest, na.rm = TRUE),
post_optimal = sum(ndvi_values <= thresholds$post_harvest, na.rm = TRUE),
still_growing = sum(ndvi_values > thresholds$early_maturity, na.rm = TRUE)
)
total_pixels <- sum(!is.na(ndvi_values))
print("Harvest Timing Assessment:")
for (stage in names(harvest_assessment)) {
percentage <- round((harvest_assessment[[stage]] / total_pixels) * 100, 1)
print(paste(stage, ":", harvest_assessment[[stage]], "pixels (", percentage, "%)"))
}
}
Use water indices to assess irrigation requirements:
# Calculate water-related indices
green_band <- red_band
terra::values(green_band) <- runif(2500, 0.1, 0.2)
names(green_band) <- "Green"
# Calculate NDWI for water stress detection
ndwi <- calculate_water_index(
green = green_band,
nir = nir_band,
index_type = "NDWI",
verbose = TRUE
)
# Irrigation needs based on NDWI
ndwi_values <- terra::values(ndwi, mat = FALSE)
valid_ndwi <- ndwi_values[!is.na(ndwi_values)]
if (length(valid_ndwi) > 0) {
irrigation_zones <- ifelse(valid_ndwi < -0.3, "High Need",
ifelse(valid_ndwi < -0.1, "Moderate Need", "Adequate"))
irrigation_table <- table(irrigation_zones)
irrigation_percent <- round(prop.table(irrigation_table) * 100, 1)
print("Irrigation Needs Assessment:")
for (zone in names(irrigation_table)) {
print(paste(zone, ":", irrigation_table[[zone]], "pixels (", irrigation_percent[[zone]], "%)"))
}
# Visualize irrigation zones
irrigation_raster <- ndwi
terra::values(irrigation_raster) <- as.numeric(as.factor(irrigation_zones))
names(irrigation_raster) <- "Irrigation_Needs"
plot_raster_fast(
irrigation_raster,
title = "Irrigation Needs Assessment (1=Adequate, 2=High, 3=Moderate)",
color_scheme = "water"
)
}
Analyze crop rotation patterns using multi-temporal CDL data:
# Simulate multi-year CDL data
create_rotation_analysis <- function() {
# Create sample rotation data
rotation_data <- data.frame(
year = rep(2021:2023, each = 4),
field = rep(c("Field_A", "Field_B", "Field_C", "Field_D"), 3),
crop = c(
"Corn", "Soybeans", "Corn", "Wheat", # 2021
"Soybeans", "Corn", "Soybeans", "Corn", # 2022
"Corn", "Soybeans", "Corn", "Soybeans" # 2023
),
yield = runif(12, 80, 200)
)
return(rotation_data)
}
rotation_analysis <- create_rotation_analysis()
print("Crop Rotation Analysis:")
print(rotation_analysis)
# Analyze rotation patterns
rotation_patterns <- list()
fields <- unique(rotation_analysis$field)
for (field in fields) {
field_data <- rotation_analysis[rotation_analysis$field == field, ]
rotation_patterns[[field]] <- paste(field_data$crop, collapse = " → ")
}
print("Rotation Patterns:")
for (field in names(rotation_patterns)) {
print(paste(field, ":", rotation_patterns[[field]]))
}
Calculate sustainability indicators:
# Calculate diversity index for crop rotation
calculate_crop_diversity <- function(rotation_data) {
diversity_scores <- list()
for (field in unique(rotation_data$field)) {
field_crops <- rotation_data$crop[rotation_data$field == field]
unique_crops <- length(unique(field_crops))
total_years <- length(field_crops)
# Simple diversity score (0-1, higher = more diverse)
diversity_scores[[field]] <- unique_crops / total_years
}
return(diversity_scores)
}
diversity_scores <- calculate_crop_diversity(rotation_analysis)
print("Crop Diversity Scores (Higher = More Diverse):")
for (field in names(diversity_scores)) {
print(paste(field, ":", round(diversity_scores[[field]], 2)))
}
# Sustainability recommendations
avg_diversity <- mean(unlist(diversity_scores))
print(paste("Average field diversity:", round(avg_diversity, 2)))
if (avg_diversity < 0.5) {
print("RECOMMENDATION: Consider more diverse crop rotations")
} else if (avg_diversity > 0.8) {
print("STATUS: Good crop diversity maintained")
}
Prepare analysis results for integration with farm management systems:
# Create farm-ready data export
create_farm_export <- function(analysis_results, field_boundaries) {
# Compile key metrics for farm management
farm_data <- list(
summary_statistics = list(),
recommendations = list(),
alerts = list()
)
# Extract key metrics
if (exists("veg_stats") && length(veg_stats) > 0) {
farm_data$summary_statistics <- veg_stats
}
# Generate management recommendations
if (exists("alerts")) {
if (alerts$drought_risk > 20) {
farm_data$recommendations <- c(farm_data$recommendations,
"Increase irrigation frequency")
}
if (alerts$disease_risk > 15) {
farm_data$recommendations <- c(farm_data$recommendations,
"Monitor for disease symptoms")
}
}
return(farm_data)
}
# Export field-level results
if (exists("field_analysis") && inherits(field_analysis, "sf")) {
field_summary <- sf::st_drop_geometry(field_analysis)
# Add coordinates for GPS guidance
field_centroids <- sf::st_centroid(field_analysis)
field_coords <- sf::st_coordinates(field_centroids)
field_summary$centroid_lon <- field_coords[, 1]
field_summary$centroid_lat <- field_coords[, 2]
print("Field Summary for Farm Management:")
print(field_summary)
}
Calculate economic indicators from vegetation analysis:
# Estimate economic value based on vegetation health
calculate_economic_metrics <- function(ndvi_data, crop_prices) {
if (!exists("ndvi_values")) return(NULL)
# Simplified yield prediction based on NDVI
# (In practice, would use crop-specific models)
predicted_yield <- ifelse(ndvi_values > 0.7, "High",
ifelse(ndvi_values > 0.5, "Medium", "Low"))
yield_table <- table(predicted_yield)
# Economic projections (simplified)
economic_zones <- list(
high_yield = sum(predicted_yield == "High", na.rm = TRUE),
medium_yield = sum(predicted_yield == "Medium", na.rm = TRUE),
low_yield = sum(predicted_yield == "Low", na.rm = TRUE)
)
return(economic_zones)
}
# Calculate economic zones
if (exists("ndvi_values")) {
economic_analysis <- calculate_economic_metrics(ndvi_values,
list(corn = 5.50, soybeans = 13.00))
if (!is.null(economic_analysis)) {
total_pixels <- sum(unlist(economic_analysis))
print("Economic Potential Analysis:")
for (zone in names(economic_analysis)) {
pixels <- economic_analysis[[zone]]
percentage <- round((pixels / total_pixels) * 100, 1)
print(paste(zone, ":", pixels, "pixels (", percentage, "%)"))
}
}
}
Implement quality assurance for agricultural monitoring:
# Vegetation index quality assessment
quality_check <- function(vegetation_indices) {
qc_results <- list()
if (inherits(vegetation_indices, "SpatRaster")) {
for (i in 1:terra::nlyr(vegetation_indices)) {
index_name <- names(vegetation_indices)[i]
values <- terra::values(vegetation_indices[[i]], mat = FALSE)
qc_results[[index_name]] <- list(
total_pixels = length(values),
valid_pixels = sum(!is.na(values)),
coverage_percent = round((sum(!is.na(values)) / length(values)) * 100, 1),
value_range = range(values, na.rm = TRUE),
outliers = sum(values < -1 | values > 1, na.rm = TRUE) # For normalized indices
)
}
}
return(qc_results)
}
# Perform quality check
if (exists("agricultural_indices")) {
qc_results <- quality_check(agricultural_indices)
print("Data Quality Assessment:")
for (index in names(qc_results)) {
qc <- qc_results[[index]]
print(paste(index, "- Coverage:", qc$coverage_percent, "%, Outliers:", qc$outliers))
}
}
Support ground truth collection and validation:
# Create sampling points for field validation
create_validation_points <- function(field_boundary, n_points = 10) {
# Generate random points within field boundary
if (inherits(field_boundary, "sf")) {
sample_points <- sf::st_sample(field_boundary, n_points)
validation_sf <- sf::st_sf(
point_id = paste0("VP_", 1:length(sample_points)),
validation_type = "Ground_Truth",
geometry = sample_points
)
return(validation_sf)
}
return(NULL)
}
# Create validation points for first field
if (exists("fields_sf")) {
validation_points <- create_validation_points(fields_sf[1, ], n_points = 5)
if (!is.null(validation_points)) {
print("Validation Points Created:")
print(sf::st_drop_geometry(validation_points))
# Extract vegetation index values at validation points
if (exists("agricultural_indices")) {
validation_extracted <- universal_spatial_join(
source_data = validation_points,
target_data = agricultural_indices,
method = "extract",
verbose = FALSE
)
print("Extracted Values at Validation Points:")
validation_summary <- sf::st_drop_geometry(validation_extracted)
print(head(validation_summary))
}
}
}
Demonstrate a complete agricultural analysis workflow:
# Complete agricultural analysis workflow
run_agricultural_workflow <- function(spectral_data, cdl_data = NULL,
region_boundary = NULL) {
workflow_results <- list()
# Step 1: Calculate vegetation indices
message("Step 1: Calculating vegetation indices...")
indices <- calculate_multiple_indices(
spectral_data = spectral_data,
indices = c("NDVI", "SAVI", "DVI"),
output_stack = TRUE
)
workflow_results$vegetation_indices <- indices
# Step 2: Crop classification (if CDL available)
if (!is.null(cdl_data)) {
message("Step 2: Analyzing crop distribution...")
crop_mask <- create_crop_mask(cdl_data, "corn")
workflow_results$crop_mask <- crop_mask
}
# Step 3: Stress assessment
message("Step 3: Assessing crop stress...")
if (inherits(indices, "SpatRaster") && "NDVI" %in% names(indices)) {
ndvi_vals <- terra::values(indices[["NDVI"]], mat = FALSE)
stress_percent <- sum(ndvi_vals < 0.5, na.rm = TRUE) / sum(!is.na(ndvi_vals)) * 100
workflow_results$stress_assessment <- round(stress_percent, 1)
}
# Step 4: Generate recommendations
message("Step 4: Generating management recommendations...")
recommendations <- character()
if (!is.null(workflow_results$stress_assessment)) {
if (workflow_results$stress_assessment > 25) {
recommendations <- c(recommendations, "High stress detected - investigate causes")
}
if (workflow_results$stress_assessment < 10) {
recommendations <- c(recommendations, "Crop conditions appear favorable")
}
}
workflow_results$recommendations <- recommendations
return(workflow_results)
}
# Run the workflow
workflow_output <- run_agricultural_workflow(
spectral_data = spectral_stack
)
print("Complete Agricultural Workflow Results:")
print(paste("Stress assessment:", workflow_output$stress_assessment, "% of area"))
print("Recommendations:")
for (rec in workflow_output$recommendations) {
print(paste("-", rec))
}
GeoSpatialSuite provides comprehensive agricultural analysis through:
get_comprehensive_cdl_codes()
,
analyze_cdl_crops_dynamic()
analyze_crop_vegetation()
,
calculate_ndvi_enhanced()
calculate_water_index()
for irrigation planning# 1. Always validate your data
print("Data Validation Checklist:")
print("✓ Check coordinate reference systems")
print("✓ Verify date ranges match growing season")
print("✓ Validate vegetation index ranges")
print("✓ Confirm crop mask accuracy")
# 2. Use appropriate indices for your crop type
crop_index_recommendations <- list(
corn = c("NDVI", "EVI2", "SAVI", "DVI"),
soybeans = c("NDVI", "SAVI", "GNDVI", "DVI"),
wheat = c("NDVI", "SAVI", "MSAVI"),
general = c("NDVI", "SAVI", "DVI", "RVI")
)
print("Recommended indices by crop type:")
for (crop in names(crop_index_recommendations)) {
indices <- crop_index_recommendations[[crop]]
print(paste(crop, ":", paste(indices, collapse = ", ")))
}
# 3. Monitor throughout growing season
print("Seasonal Monitoring Schedule:")
print("- Planting: Establish baseline measurements")
print("- Early season: Monitor emergence and establishment")
print("- Mid-season: Peak growth assessment and stress detection")
print("- Late season: Maturity evaluation and harvest timing")
print("- Post-harvest: Residue analysis and planning")
# Precision agriculture workflow components
precision_ag_components <- list(
data_collection = c("Satellite imagery", "UAV surveys", "Ground sensors"),
analysis_methods = c("Vegetation indices", "Stress detection", "Yield mapping"),
decision_support = c("Variable rate applications", "Irrigation scheduling", "Harvest timing"),
validation = c("Ground truth sampling", "Yield monitoring", "Economic analysis")
)
print("Precision Agriculture Integration:")
for (component in names(precision_ag_components)) {
print(paste(component, ":", paste(precision_ag_components[[component]], collapse = ", ")))
}
GeoSpatialSuite’s agricultural applications provide:
The agricultural tools in GeoSpatialSuite provide everything needed for professional agricultural analysis and precision farming applications!
This work was developed by the GeoSpatialSuite team with contributions from: Olatunde D. Akanbi, Vibha Mandayam, Yinghui Wu, Jeffrey Yarus, Erika I. Barcelos, and Roger H. French.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.