import gradio as gr import requests import pandas as pd import plotly.express as px # ================================================================ # 1. Core Logic (Robust Data Fetching) # ================================================================ def process_species_data(species_name, habitat, water_disturbance, land_disturbance, noise_level): if not species_name: return "Please enter a species name.", None, None # --- A. Fetch Wikipedia Data (With User-Agent Fix) --- wiki_url = "https://en.wikipedia.org/w/api.php" headers = { 'User-Agent': 'BioVigilusApp/1.0 (educational-research-project)' } params = { "action": "query", "format": "json", "prop": "extracts", "titles": species_name.replace(" ", "_"), "explaintext": True, "exintro": False, } try: response = requests.get(wiki_url, params=params, headers=headers).json() pages = response.get("query", {}).get("pages", {}) if "-1" in pages: extract = f"Species '{species_name}' not found. Please check spelling (e.g., use 'Panthera tigris' instead of 'Tiger')." else: page = next(iter(pages.values())) extract = page.get("extract", "No summary available.") except Exception as e: extract = f"Connection Error: {str(e)}" # --- B. Length Enforcement (150-250 words) --- words = extract.split() # If text is too short, append educational filler if len(words) < 150: educational_filler = ( "\n\n[Additional Ecological Context]\n" f"The species {species_name} is an integral part of its local food web. " "Biodiversity loss regarding this species could trigger a trophic cascade, affecting both prey and predator populations. " "Conservationists monitor such species as bio-indicators of environmental health. " "Preserving their natural habitat is essential not just for their survival, but for the stability of the entire ecosystem. " "Effective conservation strategies include habitat restoration, anti-poaching laws, and community awareness programs." ) extract += educational_filler words = extract.split() # Cap at ~250 words summary_text = " ".join(words[:250]) + "..." # --- C. Impact Analysis --- analysis_section = f""" ------------------------------------------------ 📊 ENVIRONMENTAL IMPACT ANALYSIS ------------------------------------------------ • Target Habitat: {habitat} ⚠️ STRESS INDICATORS: • Water Stress: {water_disturbance}/100 (High levels indicate pollution or drought risk) • Land Disturbance: {land_disturbance}/100 (Reflects habitat fragmentation or loss) • Noise Pollution: {noise_level}/100 (Impacts communication and breeding patterns) """ final_output = summary_text + analysis_section # --- D. Fetch GBIF Map Data --- gbif_url = f"https://api.gbif.org/v1/occurrence/search?scientificName={species_name}&limit=300" coords = [] try: gbif_res = requests.get(gbif_url).json() results = gbif_res.get("results", []) for r in results: if r.get("decimalLatitude") and r.get("decimalLongitude"): coords.append({"lat": r.get("decimalLatitude"), "lon": r.get("decimalLongitude")}) except: pass if coords: df = pd.DataFrame(coords) fig = px.scatter_mapbox(df, lat="lat", lon="lon", zoom=1, height=350) fig.update_layout(mapbox_style="open-street-map", margin={"r":0,"t":0,"l":0,"b":0}) else: fig = px.scatter_mapbox(pd.DataFrame({"lat":[], "lon":[]}), lat="lat", lon="lon", zoom=0) fig.update_layout(mapbox_style="open-street-map", margin={"r":0,"t":0,"l":0,"b":0}) # --- E. Create Download File --- filename = "BioVigilus_Report.txt" with open(filename, "w", encoding="utf-8") as f: f.write(f"=== BioVigilus Project Report ===\n{final_output}") return final_output, fig, filename # ================================================================ # 2. VIBRANT CSS (Safe Mode) # ================================================================ vibrant_css = """ """ # ================================================================ # 3. UI Layout # ================================================================ with gr.Blocks() as demo: gr.HTML(vibrant_css) gr.HTML("""
🌿 BioVigilus
Advanced Biodiversity & Environmental Stress Analyzer
""") with gr.Row(): # --- LEFT: INPUTS --- with gr.Column(elem_classes="custom-card"): gr.Markdown("### 🔍 Species Configuration") species_name = gr.Textbox( label="Scientific Name", placeholder="e.g. Panthera tigris", value="Panthera tigris" ) habitat = gr.Dropdown( ["Tropical Rainforest", "Savanna", "Desert", "Wetlands", "Urban", "Marine"], label="Habitat Environment", value="Tropical Rainforest" ) gr.Markdown("---") gr.Markdown("### ⚠️ Environmental Stressors") water = gr.Slider(0, 100, value=25, label="Water Pollution Level") land = gr.Slider(0, 100, value=65, label="Land Degradation") noise = gr.Slider(0, 100, value=30, label="Noise Pollution (dB)") analyze_btn = gr.Button("🚀 Run Analysis", variant="primary") # --- RIGHT: OUTPUTS --- with gr.Column(elem_classes="custom-card"): gr.Markdown("### 📊 Analysis Results") # REMOVED 'show_copy_button' to fix crash out_summary = gr.Textbox( label="Ecological Summary & Impact Report", lines=12, interactive=False ) out_map = gr.Plot(label="Global Occurrence Map") out_file = gr.File(label="📥 Download Full Report") analyze_btn.click( process_species_data, inputs=[species_name, habitat, water, land, noise], outputs=[out_summary, out_map, out_file] ) if __name__ == "__main__": demo.launch()