import gradio as gr import math # ───────────────────────────────────────────── # CORE SCIENCE ENGINE # ───────────────────────────────────────────── STAR_TYPES = { "O": {"hz_min": 100, "hz_max": 200, "uv_risk": 10, "lifespan_gyr": 0.01}, "B": {"hz_min": 50, "hz_max": 100, "uv_risk": 9, "lifespan_gyr": 0.1}, "A": {"hz_min": 15, "hz_max": 40, "uv_risk": 7, "lifespan_gyr": 2}, "F": {"hz_min": 1.5, "hz_max": 3.0, "uv_risk": 5, "lifespan_gyr": 4}, "G": {"hz_min": 0.9, "hz_max": 1.5, "uv_risk": 3, "lifespan_gyr": 10}, "K": {"hz_min": 0.3, "hz_max": 0.9, "uv_risk": 2, "lifespan_gyr": 30}, "M": {"hz_min": 0.1, "hz_max": 0.3, "uv_risk": 4, "lifespan_gyr": 100}, } def clamp(value, lo=0, hi=100): return max(lo, min(hi, value)) def analyze_planet(planet_name, radius_earth, mass_earth, temperature_k, stellar_flux, star_type, orbital_period_days): star = STAR_TYPES.get(star_type.upper(), STAR_TYPES["G"]) risks = [] # ── 1. GRAVITY SUITABILITY ────────────────────────────── # Simple approximation: g ∝ mass / radius² surface_gravity = mass_earth / (radius_earth ** 2) if 0.5 <= surface_gravity <= 2.0: gravity_score = 100 gravity_label = "✅ Uygun (%.2fg)" % surface_gravity elif surface_gravity < 0.5: gravity_score = clamp(surface_gravity / 0.5 * 80) gravity_label = "⚠️ Düşük yerçekimi (%.2fg)" % surface_gravity risks.append("Düşük yerçekimi atmosfer kaybına yol açabilir.") elif surface_gravity <= 3.0: gravity_score = clamp(100 - (surface_gravity - 2.0) * 30) gravity_label = "⚠️ Yüksek yerçekimi (%.2fg)" % surface_gravity risks.append("Yüksek yerçekimi biyolojik yapıları zorlayabilir.") else: gravity_score = clamp(100 - (surface_gravity - 2.0) * 25) gravity_label = "❌ Aşırı yerçekimi (%.2fg)" % surface_gravity risks.append("Aşırı yerçekimi çok hücreli yaşamla uyumsuz olabilir.") # ── 2. TEMPERATURE & LIQUID WATER ─────────────────────── LIQUID_MIN, LIQUID_MAX = 273, 373 # Kelvin (1 atm baseline) if LIQUID_MIN <= temperature_k <= LIQUID_MAX: temp_score = 100 water_label = "✅ Sıvı su mümkün (%d K)" % temperature_k elif temperature_k < 273: delta = 273 - temperature_k temp_score = clamp(100 - delta * 1.2) water_label = "🧊 Donma riski (%d K)" % temperature_k risks.append("Sıcaklık donma noktasının altında – sıvı su kısıtlı.") else: delta = temperature_k - 373 temp_score = clamp(100 - delta * 1.5) water_label = "🔥 Kaynama riski (%d K)" % temperature_k risks.append("Yüksek sıcaklık yüzey suyunu buharlaştırabilir.") # ── 3. STELLAR FLUX & ATMOSPHERE STABILITY ────────────── # Earth baseline ≈ 1.0 S⊕ if 0.5 <= stellar_flux <= 1.5: flux_score = 100 atm_label = "✅ Kararlı enerji akısı (%.2f S⊕)" % stellar_flux elif stellar_flux < 0.5: flux_score = clamp(stellar_flux / 0.5 * 80) atm_label = "❄️ Düşük akı – buzul riski (%.2f S⊕)" % stellar_flux risks.append("Düşük yıldız akısı global donmaya neden olabilir.") elif stellar_flux <= 2.5: flux_score = clamp(100 - (stellar_flux - 1.5) * 40) atm_label = "☀️ Yüksek akı – ısınma riski (%.2f S⊕)" % stellar_flux risks.append("Venüs benzeri sera etkisi riski mevcut.") else: flux_score = clamp(100 - (stellar_flux - 2.5) * 30) atm_label = "🌋 Aşırı akı – sera etkisi (%.2f S⊕)" % stellar_flux risks.append("Yoğun atmosfer erozyonu ve radyasyon tehdidi.") # ── 4. RADIATION RISK ─────────────────────────────────── uv_base = star["uv_risk"] # M dwarfları flare riski taşır if star_type.upper() == "M": risks.append("M cüce yıldızları sık güneş patlaması (flare) üretir – radyasyon dalgalanmaları.") if orbital_period_days < 10 and star_type.upper() in ("M", "K"): risks.append("Kısa orbital periyot: tidal kilitlenme (tidal locking) ihtimali yüksek.") radiation_score = clamp(100 - uv_base * 8) rad_label = { 1: "✅ Minimum radyasyon", 2: "✅ Düşük radyasyon", 3: "✅ Orta-düşük radyasyon", 4: "⚠️ Orta radyasyon", 5: "⚠️ Yüksek radyasyon", 6: "❌ Tehlikeli radyasyon", 7: "❌ Çok tehlikeli", 8: "❌ Ölümcül", 9: "☢️ Şiddetli", 10: "☢️ Felaket seviyesi" }.get(uv_base, "⚠️ Bilinmeyen") # ── 5. SIZE SUITABILITY ────────────────────────────────── if 0.5 <= radius_earth <= 1.8: size_bonus = 10 elif radius_earth < 0.5: size_bonus = -10 risks.append("Çok küçük gezegen – atmosfer tutma kapasitesi sınırlı.") elif radius_earth <= 2.5: size_bonus = 0 else: size_bonus = -15 risks.append("Süper-Jüpiter veya mini-Neptün sınırında – kayalık yüzey olmayabilir.") # ── 6. ORBITAL PERIOD BONUS ───────────────────────────── hz_min = star["hz_min"] hz_max = star["hz_max"] orbital_au_approx = (orbital_period_days / 365.25) ** (2/3) if hz_min <= orbital_au_approx <= hz_max: orbital_bonus = 5 else: orbital_bonus = -5 risks.append("Yörünge yaşanabilir bölge (habitable zone) dışında görünüyor.") # ── COMPOSITE SCORES ──────────────────────────────────── habitability_score = clamp( gravity_score * 0.25 + temp_score * 0.35 + flux_score * 0.20 + radiation_score * 0.20 + size_bonus + orbital_bonus ) # Life probability: daha temkinli, logaritmik life_base = habitability_score star_life_factor = min(star["lifespan_gyr"] / 4.0, 2.5) # evrim için zaman life_probability = clamp(life_base * 0.6 * min(star_life_factor, 1.5)) # ── VERDICT ───────────────────────────────────────────── if habitability_score >= 70: verdict = "🟢 YAŞANABİLİR" elif habitability_score >= 40: verdict = "🟡 KISMİ (Koşullu)" else: verdict = "🔴 YAŞANAMAz" # ── FORMAT OUTPUT ─────────────────────────────────────── explanation = build_explanation( planet_name, star_type, radius_earth, mass_earth, temperature_k, stellar_flux, orbital_period_days, surface_gravity, orbital_au_approx, star ) output = f""" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🪐 PLANET: {planet_name.upper()} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🌍 HABITABİLİTY SCORE : {habitability_score:.1f} / 100 👽 ALIEN LIFE PROBABILITY: {life_probability:.1f} % ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📊 ALT ANALİZ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🌡️ Sıvı Su Potansiyeli : {water_label} 🛡️ Atmosfer Kararlılığı : {atm_label} ☢️ Radyasyon Riski : {rad_label} ⚖️ Yerçekimi Uygunluğu : {gravity_label} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🧠 BİLİMSEL AÇIKLAMA ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ {explanation} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ⚠️ RİSK FAKTÖRLERİ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ """ if risks: for r in risks: output += f" • {r}\n" else: output += " ✅ Kritik risk faktörü tespit edilmedi.\n" output += f""" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 🌌 FINAL VERDICT ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ {verdict} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ """ return output def build_explanation(name, star_type, radius, mass, temp, flux, period, gravity, au, star): hz_mid = (star["hz_min"] + star["hz_max"]) / 2 in_hz = "yaşanabilir bölge içinde" if star["hz_min"] <= au <= star["hz_max"] \ else "yaşanabilir bölge dışında" return ( f"{name}, bir {star_type} tipi yıldızın yörüngesinde, " f"yaklaşık {au:.2f} AU uzaklıkta ({in_hz}) yer almaktadır. " f"Dünya'nın {radius:.2f} katı yarıçapı ve {mass:.2f} katı kütlesiyle " f"yüzey yerçekimi ~{gravity:.2f}g olarak hesaplanmıştır. " f"\n\n" f"Yüzey sıcaklığı {temp} K ({temp - 273:.0f}°C), " f"sıvı su koridoru (273–373 K) ile karşılaştırıldığında " f"{'bu aralık içindedir' if 273 <= temp <= 373 else 'bu aralığın dışındadır'}. " f"Yıldız akısı {flux:.2f} S⊕ olup Dünya referansına " f"({'yakın' if 0.7 <= flux <= 1.3 else 'görece uzak'}) düşmektedir. " f"\n\n" f"{star_type} tipi yıldızın tahmini ömrü ~{star['lifespan_gyr']:.0f} milyar yıldır; " f"{'bu, karmaşık yaşam evrimine yeterli zamanı temsil eder' if star['lifespan_gyr'] >= 4 else 'bu süre karmaşık yaşamın evrimleşmesi için yetersiz olabilir'}. " f"Orbital periyot {period:.1f} gün; " f"{'tidal kilitlenme olasılığı düşük' if period > 20 else 'kısa periyot tidal kilitlenmeye işaret edebilir'}." ) # ───────────────────────────────────────────── # GRADIO INTERFACE # ───────────────────────────────────────────── EXAMPLES = [ ["Kepler-452b", 1.63, 3.0, 265, 1.10, "G", 385.0], ["TRAPPIST-1e", 0.92, 0.77, 251, 0.38, "M", 6.1], ["HD 40307g", 2.50, 8.0, 226, 0.40, "K", 197.8], ["Proxima Cen b",1.08, 1.27, 234, 0.65, "M", 11.2], ["55 Cancri f", 0.96, 0.14, 300, 0.47, "G", 260.7], ] CSS = """ body { font-family: 'Courier New', monospace; } .gradio-container { max-width: 960px; margin: auto; } #title { text-align: center; } """ with gr.Blocks(title="🪐 Exoplanet Intelligence Engine") as demo: gr.Markdown( """ # 🪐 Exoplanet Intelligence Engine ### Gezegen verilerini gir — yaşanabilirliği keşfet. > *Bilimsel tahmin motoru · Gerçek NASA verisi içermez · Fizik tabanlı sezgisel model* """, elem_id="title" ) with gr.Row(): with gr.Column(scale=1): planet_name = gr.Textbox(label="🏷️ Gezegen Adı", placeholder="ör. Kepler-452b", value="MyPlanet-X") radius_earth = gr.Slider( label="📏 Yarıçap (R⊕)", minimum=0.1, maximum=15.0, step=0.01, value=1.0) mass_earth = gr.Slider( label="⚖️ Kütle (M⊕)", minimum=0.01, maximum=30.0, step=0.01, value=1.0) temperature_k = gr.Slider( label="🌡️ Yüzey Sıcaklığı (K)",minimum=50, maximum=800, step=1, value=288) stellar_flux = gr.Slider( label="☀️ Yıldız Akısı (S⊕)", minimum=0.01, maximum=10.0, step=0.01, value=1.0) star_type = gr.Dropdown(label="⭐ Yıldız Tipi", choices=["O","B","A","F","G","K","M"], value="G") orbital_period = gr.Slider( label="🔄 Orbital Periyot (gün)", minimum=1, maximum=1000, step=0.1, value=365.0) analyze_btn = gr.Button("🔭 ANALİZ ET", variant="primary") with gr.Column(scale=2): output_box = gr.Textbox( label="📋 Analiz Raporu", lines=38, max_lines=60, ) gr.Examples( examples=EXAMPLES, inputs=[planet_name, radius_earth, mass_earth, temperature_k, stellar_flux, star_type, orbital_period], label="🌌 Hazır Örnek Gezegenler" ) analyze_btn.click( fn=analyze_planet, inputs=[planet_name, radius_earth, mass_earth, temperature_k, stellar_flux, star_type, orbital_period], outputs=output_box ) gr.Markdown( """ --- **Model Notları:** Yerçekimi `g = M/R²` yaklaşımı kullanır. Yaşanabilir bölge sınırları yıldız tipine göre değişir. Radyasyon riski yıldız sınıfından türetilir. Hayat olasılığı, habitability skoru ve yıldız ömrünün fonksiyonudur. """ ) if __name__ == "__main__": demo.launch(css=CSS)