First_agent_template / tools /star_in_my_sky.py
Sudip Datta
fix spacing
76f890f
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")