Spaces:
Sleeping
Sleeping
| 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) | |