from flask import Flask, render_template, request, jsonify import requests from google import genai from google.genai import types # for configuration types import markdown import os app = Flask(__name__) # Mapping of SoilGrids parameter codes to descriptive names and explanations PARAM_MAP = { "bdod": ("Bulk Density", "Mass of dry soil per unit volume (cg/cm³)"), "cec": ("Cation Exchange Capacity", "Soil's ability to hold essential nutrients (mmol(c)/kg)"), "cfvo": ("Coarse Fragment Volume", "Volume fraction of coarse fragments in soil (cm³/dm³)"), "clay": ("Clay Content", "Amount of clay in the soil (g/kg)"), "nitrogen": ("Nitrogen Content", "Soil nitrogen levels (cg/kg)"), "ocd": ("Organic Carbon Density", "Organic carbon per unit volume (dg/dm³)"), "ocs": ("Organic Carbon Stock", "Organic carbon per unit mass (dg/kg)"), "phh2o": ("Soil pH", "Acidity or alkalinity of the soil"), "sand": ("Sand Content", "Amount of sand in the soil (g/kg)"), "silt": ("Silt Content", "Amount of silt in the soil (g/kg)"), "soc": ("Soil Organic Carbon", "Concentration of organic carbon in the soil (dg/kg)"), "wv0010": ("Water Content (0-10cm)", "Water content for shallow soil layers (10^-2 cm³/cm³)"), "wv0033": ("Water Content (0-33cm)", "Water content for intermediate soil layers (10^-2 cm³/cm³)"), "wv1500": ("Water Content (1500mm)", "Water content for deep soil layers (10^-2 cm³/cm³)") } @app.route('/') def index(): return render_template('index1.html') @app.route('/get_soil_report', methods=['POST']) def get_soil_report(): data = request.get_json() lat = data.get("lat") lon = data.get("lon") if not lat or not lon: return jsonify({"error": "Latitude and Longitude are required"}), 400 headers = {"accept": "application/json"} timeout_val = 10 # seconds # Fetch Soil Classification classification_url = "https://dev-rest.isric.org/soilgrids/v2.0/classification/query" classification_params = { "lon": lon, "lat": lat, "number_classes": "5" } try: class_response = requests.get(classification_url, params=classification_params, headers=headers, timeout=timeout_val) class_response.raise_for_status() class_data = class_response.json() except Exception as e: return jsonify({"error": "Failed to fetch soil classification: " + str(e)}), 500 soil_classification = { "soil_type": class_data.get("wrb_class_name", "Unknown"), "soil_probabilities": class_data.get("wrb_class_probability", []) } # Fetch Soil Properties properties_url = "https://dev-rest.isric.org/soilgrids/v2.0/properties/query" properties_params = { "lon": lon, "lat": lat, "property": [ "bdod", "cec", "cfvo", "clay", "nitrogen", "ocd", "ocs", "phh2o", "sand", "silt", "soc", "wv0010", "wv0033", "wv1500" ], "depth": "5-15cm", "value": "mean" } try: prop_response = requests.get(properties_url, params=properties_params, headers=headers, timeout=timeout_val) prop_response.raise_for_status() prop_data = prop_response.json() except Exception as e: return jsonify({"error": "Failed to fetch soil properties: " + str(e)}), 500 properties_list = [] layers = prop_data.get("properties", {}).get("layers", []) for layer in layers: param_code = layer.get("name") readable_name, description = PARAM_MAP.get(param_code, (param_code.upper(), "No description available")) # Get the 'mean' value for the first depth entry value = layer.get("depths", [{}])[0].get("values", {}).get("mean") if value is not None: if param_code in ["wv0010", "wv0033", "wv1500"]: final_value = value / 10.0 unit = layer.get("unit_measure", {}).get("target_units", "") elif param_code == "phh2o": final_value = value / 10.0 unit = layer.get("unit_measure", {}).get("mapped_units", "").replace("*10", "").strip() or "pH" else: final_value = value unit = layer.get("unit_measure", {}).get("mapped_units", "") else: final_value = "No Data" unit = "" properties_list.append({ "parameter": readable_name, "value": final_value, "unit": unit, "description": description }) soil_report = { "classification": soil_classification, "properties": properties_list } return jsonify(soil_report) @app.route('/analyze_soil', methods=['POST']) def analyze_soil(): data = request.get_json() soil_report = data.get("soil_report") lat = data.get("lat") lon = data.get("lon") language = data.get("language", "English") if not soil_report or not lat or not lon: return jsonify({"error": "Incomplete data"}), 400 # Extract soil classification and properties details classification_data = soil_report.get("classification", {}) soil_classification = classification_data.get("soil_type", "Unknown") soil_properties = soil_report.get("properties", []) prompt = f""" Here is the soil report data: - Classification: {classification_data} - Soil Type: {soil_classification} - Properties: {soil_properties} - Location: Latitude {lat}, Longitude {lon} Please generate a detailed soil report analysis with the following format: 1. A large, green, bold heading titled **Soil Report Analysis**. 2. Below that, display the soil type (left-aligned in black bold text) with proper spacing. 3. List 2-3 bullet points providing insights on the soil type and location. 4. Include a green-colored table listing soil parameters, their values, ranges (high, low, normal), and comments on these ranges. 5. Provide a suitable crops table in green with proper spacing, listing recommended crops based on the soil parameters, soil type, and location. 6. Finally, offer insights on fertilization type, irrigation type, and suitable agricultural practices. Format the entire output in Markdown for proper HTML rendering. diont give any useless cointnent except the reosnse liek i will search , i will reocmende,i cannotngive ex(just exmaples), proper tbales,allignment,jsutification,spaicng prpepr formatting and good look etc. Please provide the analysis in {language}. """ try: api_key = os.getenv("GEMINI_API") # Initialize the new Google GenAI client using Gemini 1.5 Flash client = genai.Client(api_key=api_key) response = client.models.generate_content( model="gemini-1.5-flash", contents=prompt, ) analysis = response.text # Remove any triple quotes if present if analysis.startswith("'''") and analysis.endswith("'''"): analysis = analysis[3:-3] except Exception as e: analysis = "Gemini analysis not available: " + str(e) analysis = markdown.markdown(analysis) return jsonify({"analysis": analysis}) if __name__ == '__main__': app.run(debug=True, port=7860)