Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, HTTPException | |
| from starlette.responses import JSONResponse | |
| from obspy.clients.fdsn import Client | |
| from obspy.core.utcdatetime import UTCDateTime | |
| import logging | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO) | |
| # Initialize the FastAPI app | |
| app = FastAPI( | |
| title="Earthquake Catalog API", | |
| description="An API to fetch earthquake data from the IRIS FDSN web service, ready for Hugging Face.", | |
| version="1.0.0", | |
| ) | |
| # Initialize the IRIS FDSN client | |
| try: | |
| client = Client("IRIS") | |
| logging.info("Successfully initialized IRIS FDSN client.") | |
| except Exception as e: | |
| client = None | |
| logging.error(f"Could not initialize IRIS FDSN client on startup: {e}") | |
| def greet_json(): | |
| """ | |
| A simple 'Hello World' endpoint. | |
| """ | |
| return {"Hello": "World!", "message": "Go to /earthquakes to fetch data, or /docs for the API documentation. Dayi"} | |
| async def get_earthquake_catalog(): | |
| """ | |
| Fetches earthquake data with a magnitude larger than 5.0 | |
| from 2015-01-05 to 2016-03-05. | |
| """ | |
| if not client: | |
| raise HTTPException( | |
| status_code=503, # Service Unavailable | |
| detail="The IRIS FDSN client is not available or failed to initialize.", | |
| ) | |
| try: | |
| starttime = UTCDateTime("2015-01-05") | |
| endtime = UTCDateTime("2016-03-05") | |
| min_magnitude = 5.0 | |
| logging.info(f"Fetching events from {starttime} to {endtime} with min magnitude {min_magnitude}.") | |
| catalog = client.get_events( | |
| starttime=starttime, | |
| endtime=endtime, | |
| minmagnitude=min_magnitude, | |
| ) | |
| logging.info(f"Found {len(catalog)} events. Now processing.") | |
| earthquake_list = [] | |
| # --- Key Change Start --- | |
| # Loop through each event and process it individually to prevent one bad event from crashing the app. | |
| for event in catalog: | |
| try: | |
| # Ensure the event has a preferred origin and magnitude | |
| if not event.preferred_origin() or not event.preferred_magnitude(): | |
| continue # Skip to the next event if essential data is missing | |
| origin = event.preferred_origin() | |
| magnitude = event.preferred_magnitude() | |
| # Safely extract the place description | |
| place = "N/A" | |
| if event.descriptions: # Check if the descriptions list exists and is not empty | |
| place = event.descriptions[0].text | |
| earthquake_list.append({ | |
| "time": origin.time.isoformat(), | |
| "latitude": origin.latitude, | |
| "longitude": origin.longitude, | |
| "depth_km": origin.depth / 1000.0 if origin.depth is not None else None, | |
| "magnitude": magnitude.mag, | |
| "magnitude_type": magnitude.magnitude_type, | |
| "place": place, | |
| }) | |
| except Exception as e: | |
| # If a single event fails, log it and continue with the others. | |
| logging.warning(f"Skipping one event due to a processing error: {e}") | |
| continue | |
| # --- Key Change End --- | |
| logging.info(f"Successfully processed {len(earthquake_list)} events.") | |
| return JSONResponse(content={"earthquakes": earthquake_list}) | |
| except Exception as e: | |
| logging.error(f"A major error occurred during the request: {e}") | |
| raise HTTPException( | |
| status_code=500, # Internal Server Error | |
| detail=f"An internal error occurred: {e}", | |
| ) |