| """ |
| STEP 5 — Parameter Estimation |
| Calculate planet radius, orbital distance, and equilibrium temperature. |
| """ |
|
|
| from typing import Dict, Optional |
| import numpy as np |
|
|
| |
| G = 6.67430e-11 |
| MSUN = 1.98847e30 |
| RSUN = 6.957e8 |
| AU = 1.495978707e11 |
| REARTH = 6.371e6 |
|
|
|
|
| def estimate_parameters( |
| tls_results: Dict, |
| star_radius: float = 1.0, |
| star_mass: float = 1.0, |
| star_temp: float = 5778.0, |
| ) -> Dict: |
| """ |
| Estimate planetary parameters from TLS results and stellar properties. |
| |
| Args: |
| tls_results: Output from step2_tls.find_period() |
| star_radius: Stellar radius in solar radii (R_sun) |
| star_mass: Stellar mass in solar masses (M_sun) |
| star_temp: Stellar effective temperature in Kelvin |
| |
| Returns: |
| Dictionary with: |
| - planet_radius: Planet radius in Earth radii (R_earth) |
| - planet_radius_rearth: Alias for planet_radius |
| - orbital_distance: Semi-major axis in AU |
| - equilibrium_temperature: Planet equilibrium temperature in K |
| - orbital_period_days: Orbital period in days |
| - transit_depth_pct: Transit depth as percentage |
| - transit_duration_hours: Transit duration in hours |
| """ |
| if not tls_results: |
| return _empty_params() |
|
|
| period_days = tls_results["period"] |
| depth_raw = tls_results["depth"] |
| duration_days = tls_results["duration"] |
|
|
| depth_frac = 1.0 - depth_raw |
|
|
| |
| |
| |
| planet_radius_rsun = star_radius * np.sqrt(depth_frac) |
| planet_radius_rearth = planet_radius_rsun * RSUN / REARTH |
|
|
| |
| |
| |
| period_seconds = period_days * 86400.0 |
| star_mass_kg = star_mass * MSUN |
|
|
| a_meters = (G * star_mass_kg * period_seconds**2 / (4 * np.pi**2))**(1/3) |
| orbital_distance_au = a_meters / AU |
|
|
| |
| |
| |
| albedo = 0.3 |
| star_radius_m = star_radius * RSUN |
| equilibrium_temperature = star_temp * np.sqrt( |
| star_radius_m / (2 * a_meters) |
| ) * (1 - albedo)**0.25 |
|
|
| return { |
| "planet_radius": float(planet_radius_rearth), |
| "planet_radius_rearth": float(planet_radius_rearth), |
| "orbital_distance": float(orbital_distance_au), |
| "equilibrium_temperature": float(equilibrium_temperature), |
| "orbital_period_days": float(period_days), |
| "transit_depth_pct": float(depth_frac * 100), |
| "transit_duration_hours": float(duration_days * 24), |
| } |
|
|
|
|
| def _empty_params() -> Dict: |
| """Return empty parameter structure for failed detections.""" |
| return { |
| "planet_radius": 0.0, |
| "planet_radius_rearth": 0.0, |
| "orbital_distance": 0.0, |
| "equilibrium_temperature": 0.0, |
| "orbital_period_days": 0.0, |
| "transit_depth_pct": 0.0, |
| "transit_duration_hours": 0.0, |
| } |
|
|
|
|
| def format_planet_summary(params: Dict, target_name: str = "Candidate") -> str: |
| """Generate a formatted planet summary card.""" |
| lines = [ |
| f"{target_name}", |
| "─" * 32, |
| f"Period: {params['orbital_period_days']:.2f} days", |
| f"Radius: {params['planet_radius_rearth']:.2f} R⊕", |
| f"Orbital Dist: {params['orbital_distance']:.3f} AU", |
| f"Temperature: {params['equilibrium_temperature']:.0f} K " |
| f"({params['equilibrium_temperature'] - 273.15:.0f}°C)", |
| f"Depth: {params['transit_depth_pct']:.3f}%", |
| f"Duration: {params['transit_duration_hours']:.1f} hours", |
| ] |
| return "\n".join(lines) |
|
|
|
|
| def classify_planet_type(planet_radius_rearth: float) -> str: |
| """Classify planet by radius.""" |
| if planet_radius_rearth < 1.25: |
| return "Earth-sized" |
| elif planet_radius_rearth < 2.0: |
| return "Super-Earth" |
| elif planet_radius_rearth < 4.0: |
| return "Sub-Neptune" |
| elif planet_radius_rearth < 8.0: |
| return "Neptune-sized" |
| elif planet_radius_rearth < 12.0: |
| return "Sub-Jupiter" |
| else: |
| return "Jupiter-sized" |