Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| RRF Φ5.2 - Resonance of Reality Framework | |
| Hugging Face Spaces Interactive Application - FIXED FOR HF COMPATIBILITY | |
| Author: A. Padilla Morales | |
| ORCID: 0009-0000-3530-2146 | |
| """ | |
| import numpy as np | |
| import pandas as pd | |
| import warnings | |
| warnings.filterwarnings('ignore') | |
| from scipy import sparse, linalg | |
| import networkx as nx | |
| import matplotlib.pyplot as plt | |
| import gradio as gr | |
| # ============================================================================ | |
| # RRF CONFIGURATION & INITIALIZATION | |
| # ============================================================================ | |
| class RRFConfig: | |
| """RRF Φ5.2 configuration""" | |
| def __init__(self): | |
| self.model_version = "Phi 5.2" | |
| self.manifold_type = "Subdivided Icosahedral" | |
| self.num_nodes = 12 | |
| self.dirac_gap_ev = 0.092 | |
| self.fiedler_n12 = 2.974914 | |
| self.mean_sparc_coherence = 0.8163 | |
| self.symmetry_breaking_threshold = 0.000204 | |
| class IcosahedralManifold: | |
| """12-node icosahedral discrete manifold""" | |
| def __init__(self, num_nodes=12): | |
| self.num_nodes = num_nodes | |
| self.eigenvalues = None | |
| self.eigenvectors = None | |
| self._construct() | |
| def _construct(self): | |
| """Build icosahedron""" | |
| phi = (1 + np.sqrt(5)) / 2 | |
| vertices = np.array([ | |
| [1, phi, 0], [-1, phi, 0], [1, -phi, 0], [-1, -phi, 0], | |
| [0, 1, phi], [0, -1, phi], [0, 1, -phi], [0, -1, -phi], | |
| [phi, 0, 1], [-phi, 0, 1], [phi, 0, -1], [-phi, 0, -1] | |
| ]) | |
| vertices = vertices / np.linalg.norm(vertices[0]) | |
| # Build adjacency | |
| adjacency = np.zeros((self.num_nodes, self.num_nodes)) | |
| threshold = 1.1 | |
| for i in range(self.num_nodes): | |
| for j in range(i+1, self.num_nodes): | |
| dist = np.linalg.norm(vertices[i] - vertices[j]) | |
| if dist < threshold: | |
| adjacency[i, j] = 1.0 | |
| adjacency[j, i] = 1.0 | |
| # Laplacian | |
| degrees = adjacency.sum(axis=1) | |
| degree_matrix = np.diag(degrees) | |
| laplacian = degree_matrix - adjacency | |
| # Eigendecomposition | |
| eigenvalues, eigenvectors = np.linalg.eigh(laplacian) | |
| self.eigenvalues = eigenvalues | |
| self.eigenvectors = eigenvectors | |
| class CoherenceAnalyzer: | |
| """Compute resonance coherence""" | |
| def __init__(self, manifold): | |
| self.manifold = manifold | |
| def analyze(self, velocity_curve): | |
| """Compute coherence score""" | |
| # Interpolate to 12 nodes | |
| indices = np.linspace(0, len(velocity_curve)-1, self.manifold.num_nodes) | |
| signal_interp = np.interp(indices, np.arange(len(velocity_curve)), velocity_curve) | |
| # Project onto eigenbasis | |
| coefficients = self.manifold.eigenvectors.T @ signal_interp | |
| reconstructed = self.manifold.eigenvectors @ coefficients | |
| # Interpolate back | |
| indices_back = np.linspace(0, len(reconstructed)-1, len(velocity_curve)) | |
| reconstructed_interp = np.interp(indices_back, np.arange(len(reconstructed)), reconstructed) | |
| # Calculate coherence | |
| residuals = velocity_curve - reconstructed_interp | |
| mse = np.mean(residuals**2) | |
| signal_variance = np.var(velocity_curve) | |
| if signal_variance > 0: | |
| normalized_error = mse / signal_variance | |
| coherence = 1.0 / (1.0 + normalized_error) | |
| else: | |
| coherence = 0.5 | |
| # Energy concentration | |
| total_energy = np.sum(coefficients**2) | |
| low_mode_energy = np.sum(coefficients[:3]**2) | |
| energy_concentration = low_mode_energy / total_energy if total_energy > 0 else 0.0 | |
| return { | |
| 'coherence': float(coherence), | |
| 'rmse': float(np.sqrt(mse)), | |
| 'energy_concentration': float(energy_concentration), | |
| 'reconstructed': reconstructed_interp, | |
| 'residuals': residuals | |
| } | |
| # ============================================================================ | |
| # INITIALIZE FRAMEWORK | |
| # ============================================================================ | |
| config = RRFConfig() | |
| manifold = IcosahedralManifold() | |
| analyzer = CoherenceAnalyzer(manifold) | |
| # ============================================================================ | |
| # ANALYSIS FUNCTIONS | |
| # ============================================================================ | |
| def analyze_rotation_curve(velocity_input): | |
| """Main analysis function""" | |
| try: | |
| # Parse input | |
| if isinstance(velocity_input, str): | |
| velocity_data = np.array([float(x.strip()) for x in velocity_input.split(',')]) | |
| else: | |
| velocity_data = np.array(velocity_input).flatten() | |
| if len(velocity_data) < 5: | |
| return "Error: Need at least 5 velocity measurements", None | |
| # Normalize | |
| velocity_data = (velocity_data - np.mean(velocity_data)) / (np.std(velocity_data) + 1e-6) | |
| # Analyze | |
| results = analyzer.analyze(velocity_data) | |
| # Create visualization | |
| fig, axes = plt.subplots(1, 2, figsize=(14, 5)) | |
| # Fit plot | |
| r = np.linspace(0, 20, len(velocity_data)) | |
| axes[0].plot(r, velocity_data, 'o-', label='Observed', linewidth=2, markersize=5, color='black') | |
| axes[0].plot(r, results['reconstructed'], 's--', label='RRF Fit', linewidth=2, color='blue') | |
| axes[0].set_xlabel('Radius (kpc)', fontsize=11) | |
| axes[0].set_ylabel('Velocity (km/s)', fontsize=11) | |
| axes[0].set_title(f'Spectral Fit (Coherence: {results["coherence"]:.4f})', fontsize=12, fontweight='bold') | |
| axes[0].legend(fontsize=10) | |
| axes[0].grid(True, alpha=0.3) | |
| # Residuals plot | |
| axes[1].bar(r, results['residuals'], color='steelblue', alpha=0.7, edgecolor='black') | |
| axes[1].axhline(y=0, color='red', linestyle='--', linewidth=2) | |
| axes[1].set_xlabel('Radius (kpc)', fontsize=11) | |
| axes[1].set_ylabel('Residuals', fontsize=11) | |
| axes[1].set_title(f'Fit Residuals (RMSE: {results["rmse"]:.4f})', fontsize=12, fontweight='bold') | |
| axes[1].grid(True, alpha=0.3, axis='y') | |
| plt.tight_layout() | |
| # Classification | |
| if results['coherence'] > 0.95: | |
| stability = "🟢 Golden Standard" | |
| elif results['coherence'] > config.mean_sparc_coherence + 0.05: | |
| stability = "🟢 High Stability" | |
| elif results['coherence'] > config.mean_sparc_coherence: | |
| stability = "🟡 Above Baseline" | |
| else: | |
| stability = "🟠 Near Baseline" | |
| report = f"""## RRF Φ5.2 Results | |
| **Coherence**: {results['coherence']:.4f} | |
| **Baseline**: {config.mean_sparc_coherence:.4f} | |
| **Change**: {((results['coherence']/config.mean_sparc_coherence - 1) * 100):+.1f}% | |
| **Stability**: {stability} | |
| **RMSE**: {results['rmse']:.4f} | |
| **Energy Concentration**: {results['energy_concentration']:.2%} | |
| --- | |
| Framework: {config.model_version} | Manifold: {config.manifold_type} | |
| """ | |
| return report, fig | |
| except Exception as e: | |
| return f"**Error**: {str(e)}", None | |
| # ============================================================================ | |
| # GRADIO INTERFACE | |
| # ============================================================================ | |
| with gr.Blocks(title="RRF Φ5.2") as demo: | |
| gr.Markdown(""" | |
| # 🌍 RRF Φ5.2 Resonance Analysis | |
| Discrete topological approach to galactic coherence | |
| **A. Padilla Morales** | ORCID: 0009-0000-3530-2146 | |
| """) | |
| with gr.Row(): | |
| with gr.Column(): | |
| velocity_input = gr.Textbox( | |
| label="Velocity Data (comma-separated)", | |
| placeholder="200, 210, 215, ...", | |
| lines=4 | |
| ) | |
| btn = gr.Button("Analyze", size="lg", variant="primary") | |
| with gr.Column(): | |
| results = gr.Markdown() | |
| plot = gr.Plot() | |
| btn.click(fn=analyze_rotation_curve, inputs=[velocity_input], outputs=[results, plot]) | |
| with gr.Accordion("Example Data"): | |
| gr.Markdown(""" | |
| **NGC 7331**: | |
| ``` | |
| 200, 210, 215, 218, 220, 221, 222, 222, 223, 223, 224, 224, 224, 225, 225, 225, 225, 226, 226, 226, 226, 227, 227, 227, 227, 227, 228, 228, 228, 228, 228, 228, 229, 229, 229, 229 | |
| ``` | |
| """) | |
| if __name__ == "__main__": | |
| demo.launch() |