Spaces:
Sleeping
Sleeping
| from astroquery.simbad import Simbad | |
| from astropy.coordinates import SkyCoord | |
| from astropy import units as u | |
| from geopy.geocoders import Nominatim | |
| from skyfield.api import load, Topos, Star | |
| from smolagents import Tool | |
| # Make sure RA/DEC fields are included in SIMBAD query | |
| Simbad.add_votable_fields("ra", "dec") | |
| class StarInMySkyTool(Tool): | |
| name = "star_in_my_sky" | |
| description = ( | |
| "Checks if a star is currently visible in the sky at a given location." | |
| "If the star is visible, it returns the location - altitude and azimuth." | |
| "If the star is not visible, it just says the star is below the horizon." | |
| "This tool expects two arguments: the name of the star and the location in English." | |
| ) | |
| inputs = { | |
| "star_name": {"type": "string", "description": "The name of the star to check."}, | |
| "location_name": {"type": "string", "description": "The location to check. e.g. London, UK"}, | |
| } | |
| output_type = "string" | |
| def forward(self, star_name: str, location_name: str) -> str: | |
| try: | |
| resp = get_star_visibility(star_name, location_name) | |
| except Exception as e: | |
| return f"Error: {str(e)}" | |
| return resp | |
| def get_coordinates_from_location(location_name): | |
| """Use geopy to convert a place name into latitude/longitude.""" | |
| geolocator = Nominatim(user_agent="astrogeo") | |
| location = geolocator.geocode(location_name) | |
| if not location: | |
| raise ValueError(f"Could not geocode location: {location_name}") | |
| return location.latitude, location.longitude | |
| def get_star_visibility(star_name, location_name): | |
| """ | |
| 1. Convert a location name to lat/long. | |
| 2. Query SIMBAD for star's RA/Dec. | |
| 3. Compute altitude/azimuth via Skyfield. | |
| 4. Print whether the star is above or below the horizon. | |
| """ | |
| # 1. Get lat/long from location name | |
| latitude, longitude = get_coordinates_from_location(location_name) | |
| print(f"Location '{location_name}': lat={latitude:.4f}, lon={longitude:.4f}") | |
| # 2. Query SIMBAD for the star's RA/DEC | |
| result_table = Simbad.query_object(star_name) | |
| if result_table is None: | |
| return f"Could not find star '{star_name}' in SIMBAD." | |
| if "ra" not in result_table.colnames or "dec" not in result_table.colnames: | |
| return "The 'ra'/'dec' columns are missing in SIMBAD’s response!" | |
| ra_str = result_table["ra"][0] # e.g. '06 45 08.92' | |
| dec_str = result_table["dec"][0] # e.g. '-16 42 58.0' | |
| # Convert RA/DEC to numeric values using Astropy | |
| skycoord = SkyCoord(ra_str, dec_str, unit=(u.hourangle, u.deg)) | |
| # 3. Create a Skyfield Star object | |
| star = Star(ra_hours=skycoord.ra.hour, dec_degrees=skycoord.dec.degree) | |
| # 4. Load ephemeris, define observer, compute alt/az for now | |
| ts = load.timescale() | |
| t = ts.now() | |
| planets = load("de421.bsp") | |
| earth = planets["earth"] | |
| observer = Topos(latitude_degrees=latitude, longitude_degrees=longitude) | |
| # Calculate altitude, azimuth | |
| alt, az, distance = (earth + observer).at(t).observe(star).apparent().altaz() | |
| resp = "" | |
| # 5. Print results | |
| if alt.degrees > 0: | |
| resp = ( | |
| f"Star '{star_name}' is above the horizon at {location_name} (NOW).\n" | |
| f"Altitude: {alt.degrees:.2f}°, Azimuth: {az.degrees:.2f}°" | |
| ) | |
| else: | |
| resp = f"\nStar '{star_name}' is below the horizon at {location_name} (NOW)." | |
| return resp | |
| if __name__ == "__main__": | |
| # Example: "Sirius", "London, UK" | |
| get_star_visibility("Sirius", "London, UK") | |