Spaces:
Sleeping
Sleeping
| """ | |
| main.py | |
| ----------------------------------------------------- | |
| # WHAT: FastAPI application entry point for the ATAS backend. | |
| # Exposes a single endpoint - POST /analyze - that accepts an aircraft | |
| # image and engagement parameters, runs the full pipeline, and returns | |
| # a JSON response. | |
| # | |
| # WHY: All five src/ modules are isolated units. main.py is the glue layer | |
| # that wires them together in the correct order and exposes the result | |
| # to the outside world via HTTP. | |
| # | |
| # USE: Called by the HUD frontend via fetch(). Also used directly during | |
| # testing via curl or a Python test script to verify end-to-end pipeline | |
| # behavior before any UI work begins. | |
| # User controls / HUD inputs: + 1 Image | |
| # your_speed, your_altitude, enemy_altitude, countermeasure_deployed, | |
| # launch_distance, remaining_distance, azimuth, elevation | |
| # Comes from aircraft_metadata.csv: | |
| # missile_speed, missile_range, enemy_generation, maneuverability | |
| # Derived by build_feature_array() internally: | |
| # closure_rate, missile_phase | |
| """ | |
| # Importing the necessary libraries | |
| from fastapi import FastAPI | |
| from fastapi import UploadFile, File, Form | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import FileResponse | |
| import tempfile | |
| import os | |
| from src.classifier import predict_aircraft | |
| from src.metadata import get_aircraft_metadata | |
| from src.physics_generator import build_feature_array | |
| from src.models import make_predictions | |
| from src.decision import get_recommendation | |
| # Creating a server | |
| app = FastAPI() | |
| # Allow the browser to send requests to this server | |
| # Without this, the HUD's fetch() call gets blocked by the browser's security rules | |
| # CORS (Cross-Origin Resource Sharing) is the mechanism where your server tells the browser: "yes, I allow requests from other origins." | |
| # allow_origins=["*"] β accept requests from any origin (local file, any URL) | |
| # allow_methods=["*"] β accept any HTTP method (POST, GET, etc.) | |
| # allow_headers=["*"] β accept any headers the browser sends with the request | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["https://eakempreet-atas.hf.space"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Now that the HUD is served from the same Space, no other origin needs access | |
| # This prevents random websites from hitting your /analyze endpoint | |
| # When a browser visits the Space URL, it sends GET / | |
| # This route catches that request and returns the HUD HTML file | |
| # FileResponse reads the file from disk and sends it with the correct content type | |
| # so the browser knows to render it as a webpage, not download it | |
| async def serve_hud(): | |
| return FileResponse("frontend/atas_hud_v11.html") | |
| # Function to take the inputs | |
| # image -> as temp file | |
| # 8 features -> form object | |
| async def analyze( | |
| image: UploadFile = File(...), # The ... just means required. No default value. | |
| your_speed: float = Form(...), # name : type = where_it_comes_from(required_or_default) | |
| your_altitude: float = Form(...), | |
| enemy_altitude: float = Form(...), | |
| countermeasure_deployed: int = Form(...), | |
| launch_distance: float = Form(...), | |
| remaining_distance: float = Form(...), | |
| azimuth: float = Form(...), | |
| elevation: float = Form(...), | |
| friendly_aircraft: str = Form(...) | |
| ): | |
| # Browser sends image as raw bytes, not a file path | |
| # predict_aircraft() needs a real file path on disk | |
| # So we write the bytes to a temp file and grab its path | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as tmp: | |
| tmp.write(await image.read()) # dump bytes from memory to disk | |
| tmp_path = tmp.name # grab the path e.g. /tmp/abc123.jpg | |
| # 1. Calling the function to predict the aircraft | |
| aircraft_name = predict_aircraft(image_path=tmp_path) | |
| # 2. Get the metadata of predicted aircraft | |
| metadata_dict = get_aircraft_metadata(aircraft_name=aircraft_name) | |
| friendly_metadata = get_aircraft_metadata(aircraft_name=friendly_aircraft) | |
| # 3. Build the features to feed the models | |
| feature_dict = build_feature_array( | |
| # From HUD sliders | |
| launch_distance=launch_distance, | |
| remaining_distance=remaining_distance, | |
| azimuth=azimuth, | |
| elevation=elevation, | |
| your_altitude=your_altitude, | |
| your_speed=your_speed, | |
| enemy_altitude=enemy_altitude, | |
| countermeasure_deployed=countermeasure_deployed, | |
| # From metadata lookup (enemy aircraft) | |
| missile_speed=metadata_dict['missile_speed'], | |
| missile_range=metadata_dict['missile_range'], | |
| enemy_generation=metadata_dict['enemy_generation'], | |
| # From metadata lookup (friendly aircraft) | |
| your_maneuverability=friendly_metadata['maneuverability'] | |
| ) | |
| # 4. Make predictions using models | |
| predictions_dict = make_predictions(feature_dict=feature_dict) | |
| # 5. Providing recommendations to the pilot | |
| suggestion = get_recommendation( | |
| eta_seconds=predictions_dict['eta_seconds'], | |
| hit_probability=predictions_dict['hit_probability'], | |
| no_aa_capability=metadata_dict['no_aa_capability'], | |
| enemy_generation=metadata_dict['enemy_generation'], | |
| friendly_generation=friendly_metadata['enemy_generation'] | |
| ) | |
| # 6. Delete the temparary file since work is done | |
| os.remove(tmp_path) | |
| # 7. Return the value predicted and derived | |
| return { | |
| 'aircraft_name' : aircraft_name, | |
| 'missile_speed' : metadata_dict['missile_speed'], | |
| 'missile_range' : metadata_dict['missile_range'], | |
| 'enemy_generation' : metadata_dict['enemy_generation'], | |
| 'maneuverability' : metadata_dict['maneuverability'], | |
| 'no_aa_capability' : metadata_dict['no_aa_capability'], | |
| 'eta_seconds' : predictions_dict['eta_seconds'], | |
| 'hit_probability' : predictions_dict['hit_probability'], | |
| 'recommendation' : suggestion | |
| } | |
| """ | |
| Request comes in | |
| β | |
| Image saved to temp file | |
| β | |
| predict_aircraft() β aircraft_name | |
| β | |
| get_aircraft_metadata() x 2 β enemy + friendly metadata | |
| β | |
| build_feature_array() β 14 feature dict | |
| β | |
| make_predictions() β eta + hit probability | |
| β | |
| get_recommendation() β tactical suggestion | |
| β | |
| Temp file deleted | |
| β | |
| JSON returned to HUD | |
| """ |