A Python wrapper and CLI for NASA's REST APIs
Project description
PyASAN 🚀
A Python wrapper and command-line interface for NASA's REST APIs, including Astronomy Picture of the Day (APOD), Mars Rover Photos, and TechTransfer APIs.
Features
- 🌟 Easy-to-use Python API for NASA's APOD, Mars Rover Photos, and TechTransfer services
- 🖥️ Beautiful command-line interface with rich formatting
- 🔴 Mars Rover Photos - Access photos from Perseverance, Curiosity, Opportunity, and Spirit
- 🔬 TechTransfer - Search NASA patents, software, and spinoff technologies
- 🔑 Flexible authentication (API key or environment variables)
- 📊 Comprehensive data models with validation
- 🛡️ Robust error handling and retry logic
- 🧪 Well-tested with comprehensive unit tests
- 📚 Extensible design for future NASA APIs
Installation
From PyPI (when published)
pip install pyasan
From Source
git clone https://github.com/yourusername/pyasan.git
cd pyasan
pip install -e .
Development Installation
git clone https://github.com/yourusername/pyasan.git
cd pyasan
pip install -e ".[dev]"
Quick Start
Get Your NASA API Key
- Visit https://api.nasa.gov/
- Fill out the form to get your free API key
- Set it as an environment variable:
export NASA_API_KEY=your_api_key_here
Python API
Astronomy Picture of the Day (APOD)
from pyasan import APODClient
# Initialize client (uses NASA_API_KEY env var by default)
client = APODClient()
# Or provide API key directly
client = APODClient(api_key="your_api_key_here")
# Get today's APOD
apod = client.get_apod()
print(f"Title: {apod.title}")
print(f"Date: {apod.date}")
print(f"URL: {apod.url}")
print(f"Explanation: {apod.explanation}")
# Get APOD for a specific date
apod = client.get_apod(date="2023-01-01", hd=True)
# Get random APOD
random_apod = client.get_random_apod()
# Get multiple random APODs
random_apods = client.get_random_apod(count=5)
for apod in random_apods:
print(apod.title)
# Get APOD for a date range
apods = client.get_apod_range(
start_date="2023-01-01",
end_date="2023-01-07"
)
# Get recent APODs
recent = client.get_recent_apods(days=7)
Mars Rover Photos
from pyasan import MarsRoverPhotosClient
# Initialize client
client = MarsRoverPhotosClient(api_key="your_api_key_here")
# Get available rovers
rovers = client.get_available_rovers()
print(rovers) # ['perseverance', 'curiosity', 'opportunity', 'spirit']
# Get photos by Martian sol (day)
photos = client.get_photos_by_sol("curiosity", sol=1000, camera="MAST")
print(f"Found {len(photos)} photos from Sol 1000")
# Get photos by Earth date
photos = client.get_photos_by_earth_date("perseverance", "2023-01-01")
for photo in photos:
print(f"Photo ID: {photo.id}, Camera: {photo.camera.full_name}")
# Get latest photos
latest = client.get_latest_photos("curiosity")
print(f"Latest photos: {len(latest)}")
# Get mission manifest
manifest = client.get_manifest("curiosity")
print(f"Total photos: {manifest.photo_manifest.total_photos:,}")
print(f"Mission status: {manifest.photo_manifest.status}")
# Get available cameras for a rover
cameras = client.get_rover_cameras("perseverance")
print(f"Perseverance cameras: {cameras}")
TechTransfer
from pyasan import TechTransferClient
# Initialize client
client = TechTransferClient(api_key="your_api_key_here")
# Search patents
patents = client.search_patents("solar energy", limit=5)
print(f"Found {len(patents)} patents")
for patent in patents:
print(f"- {patent.title}")
if patent.patent_number:
print(f" Patent Number: {patent.patent_number}")
# Search software
software = client.search_software("machine learning", limit=3)
for item in software:
print(f"- {item.title}")
if item.version:
print(f" Version: {item.version}")
# Search spinoff technologies
spinoffs = client.search_spinoffs("medical", limit=3)
for spinoff in spinoffs:
print(f"- {spinoff.title}")
if spinoff.company:
print(f" Company: {spinoff.company}")
# Search all categories at once
all_results = client.search_all("robotics", limit=2)
for category, results in all_results.items():
if not category.endswith("_error"):
print(f"{category}: {len(results)} results")
# Get available categories
categories = client.get_categories()
print(f"Available categories: {categories}")
Command Line Interface
The CLI provides a beautiful, user-friendly interface to NASA's APIs:
APOD Commands
# Get today's APOD
pyasan apod get
# Get APOD for a specific date
pyasan apod get --date 2023-01-01
# Get HD version
pyasan apod get --date 2023-01-01 --hd
# Get random APOD
pyasan apod random
# Get 5 random APODs
pyasan apod random --count 5
# Get APODs for a date range
pyasan apod range --start-date 2023-01-01 --end-date 2023-01-07
# Get recent APODs
pyasan apod recent --days 7
# Hide explanation text for cleaner output
pyasan apod get --no-explanation
Mars Rover Photos Commands
# Get photos by sol (Martian day)
pyasan mars photos --rover curiosity --sol 1000 --camera MAST
# Get photos by Earth date
pyasan mars photos --rover perseverance --earth-date 2023-01-01
# Get latest photos from a rover
pyasan mars latest --rover curiosity
# Get mission manifest
pyasan mars manifest --rover curiosity
# List available cameras for a rover
pyasan mars cameras --rover perseverance
# Get photos with pagination
pyasan mars photos --rover curiosity --sol 1000 --page 2
# Hide detailed photo information
pyasan mars photos --rover curiosity --sol 1000 --no-details
TechTransfer Commands
# Search NASA patents
pyasan techtransfer patents "solar energy" --limit 5
# Search NASA software
pyasan techtransfer software "machine learning" --limit 3
# Search NASA spinoff technologies
pyasan techtransfer spinoffs "medical devices" --limit 5
# Search across all categories
pyasan techtransfer search "robotics" --limit 3
# Search specific category only
pyasan techtransfer search "artificial intelligence" --category software
# Use pagination
pyasan techtransfer patents "space technology" --page 2 --limit 10
# Hide detailed information
pyasan techtransfer patents "propulsion" --no-details
# List available categories
pyasan techtransfer categories
Global Options
# Use specific API key for any command
pyasan apod get --api-key your_api_key_here
pyasan mars photos --rover curiosity --sol 1000 --api-key your_api_key_here
pyasan techtransfer patents "space technology" --api-key your_api_key_here
# Show version
pyasan --version
API Reference
APODClient
The main client for interacting with NASA's APOD API.
Methods
get_apod(date=None, hd=False, thumbs=False)
Get Astronomy Picture of the Day for a specific date.
Parameters:
date(str|date, optional): Date in YYYY-MM-DD format or date object. Defaults to today.hd(bool): Return HD image URL if availablethumbs(bool): Return thumbnail URL for videos
Returns: APODResponse
get_random_apod(count=1, hd=False, thumbs=False)
Get random Astronomy Picture(s) of the Day.
Parameters:
count(int): Number of random images to retrieve (1-100)hd(bool): Return HD image URLs if availablethumbs(bool): Return thumbnail URLs for videos
Returns: APODResponse if count=1, APODBatch if count>1
get_apod_range(start_date, end_date, hd=False, thumbs=False)
Get Astronomy Pictures of the Day for a date range.
Parameters:
start_date(str|date): Start date in YYYY-MM-DD format or date objectend_date(str|date): End date in YYYY-MM-DD format or date objecthd(bool): Return HD image URLs if availablethumbs(bool): Return thumbnail URLs for videos
Returns: APODBatch
get_recent_apods(days=7, hd=False, thumbs=False)
Get recent Astronomy Pictures of the Day.
Parameters:
days(int): Number of recent days to retrieve (1-100)hd(bool): Return HD image URLs if availablethumbs(bool): Return thumbnail URLs for videos
Returns: APODBatch
MarsRoverPhotosClient
The main client for interacting with NASA's Mars Rover Photos API.
Methods
get_photos(rover, sol=None, earth_date=None, camera=None, page=None)
Get Mars rover photos by sol or Earth date.
Parameters:
rover(str): Rover name (perseverance, curiosity, opportunity, spirit)sol(int, optional): Martian sol (day) - cannot be used with earth_dateearth_date(str|date, optional): Earth date in YYYY-MM-DD format - cannot be used with solcamera(str, optional): Camera abbreviation (e.g., FHAZ, RHAZ, MAST, NAVCAM)page(int, optional): Page number for pagination
Returns: MarsPhotosResponse
get_photos_by_sol(rover, sol, camera=None, page=None)
Get Mars rover photos by Martian sol.
Parameters:
rover(str): Rover namesol(int): Martian sol (day)camera(str, optional): Camera abbreviationpage(int, optional): Page number for pagination
Returns: MarsPhotosResponse
get_photos_by_earth_date(rover, earth_date, camera=None, page=None)
Get Mars rover photos by Earth date.
Parameters:
rover(str): Rover nameearth_date(str|date): Earth date in YYYY-MM-DD format or date objectcamera(str, optional): Camera abbreviationpage(int, optional): Page number for pagination
Returns: MarsPhotosResponse
get_latest_photos(rover)
Get the latest photos from a Mars rover.
Parameters:
rover(str): Rover name
Returns: MarsPhotosResponse
get_manifest(rover)
Get mission manifest for a Mars rover.
Parameters:
rover(str): Rover name
Returns: ManifestResponse
get_rover_cameras(rover)
Get list of available cameras for a rover.
Parameters:
rover(str): Rover name
Returns: List[str] - List of camera abbreviations
get_available_rovers()
Get list of available rovers.
Returns: List[str] - List of rover names
Data Models
APODResponse
Represents a single APOD entry.
Attributes:
title(str): The title of the imagedate(date): The date of the imageexplanation(str): The explanation of the imageurl(str): The URL of the imagemedia_type(str): The type of media (image or video)hdurl(str, optional): The URL of the HD imagethumbnail_url(str, optional): The URL of the thumbnailcopyright(str, optional): The copyright information
Properties:
is_video(bool): Check if the media is a videois_image(bool): Check if the media is an image
APODBatch
Represents multiple APOD entries.
Attributes:
items(List[APODResponse]): List of APOD responses
Methods:
__len__(): Get the number of items__iter__(): Iterate over items__getitem__(index): Get item by index
MarsPhoto
Represents a single Mars rover photo.
Attributes:
id(int): Photo IDsol(int): Martian sol (day)camera(Camera): Camera informationimg_src(str): Image source URLearth_date(date): Earth date when photo was takenrover(Rover): Rover information
MarsPhotosResponse
Represents multiple Mars rover photos.
Attributes:
photos(List[MarsPhoto]): List of Mars photos
Methods:
__len__(): Get the number of photos__iter__(): Iterate over photos__getitem__(index): Get photo by index
MissionManifest
Represents a Mars rover mission manifest.
Attributes:
name(str): Rover namelanding_date(date): Landing date on Marslaunch_date(date): Launch date from Earthstatus(str): Mission statusmax_sol(int): Maximum sol with photosmax_date(date): Most recent Earth date with photostotal_photos(int): Total number of photosphotos(List[ManifestPhoto]): Photo information by sol
Camera
Represents camera information.
Attributes:
id(int): Camera IDname(str): Camera abbreviationrover_id(int): Rover IDfull_name(str): Full camera name
Rover
Represents rover information.
Attributes:
id(int): Rover IDname(str): Rover namelanding_date(date): Landing date on Marslaunch_date(date): Launch date from Earthstatus(str): Mission status
TechTransferClient
The main client for interacting with NASA's TechTransfer API.
Methods
search_patents(query, limit=None, page=None)
Search NASA patents by query string.
Parameters:
query(str): Search query stringlimit(int, optional): Maximum number of results (1-100)page(int, optional): Page number for pagination
Returns: TechTransferPatentResponse containing patent results
search_software(query, limit=None, page=None)
Search NASA software by query string.
Parameters:
query(str): Search query stringlimit(int, optional): Maximum number of results (1-100)page(int, optional): Page number for pagination
Returns: TechTransferSoftwareResponse containing software results
search_spinoffs(query, limit=None, page=None)
Search NASA spinoff technologies by query string.
Parameters:
query(str): Search query stringlimit(int, optional): Maximum number of results (1-100)page(int, optional): Page number for pagination
Returns: TechTransferSpinoffResponse containing spinoff results
search_all(query, category=None, limit=None, page=None)
Search across all TechTransfer categories or a specific category.
Parameters:
query(str): Search query stringcategory(str, optional): Specific category ('patent', 'software', 'spinoff')limit(int, optional): Maximum number of results per categorypage(int, optional): Page number for pagination
Returns: Dictionary with category names as keys and response objects as values
get_categories()
Get list of available TechTransfer categories.
Returns: List of category names
TechTransfer Data Models
TechTransferPatent
Represents a NASA patent.
Attributes:
id(str): Patent IDtitle(str): Patent titleabstract(str): Patent abstractpatent_number(str): Patent numbercase_number(str): NASA case numberpublication_date(date): Publication datecategory(str): Technology categorycenter(str): NASA centerinnovator(str): Inventor/innovatorcontact(str): Contact information
TechTransferSoftware
Represents NASA software.
Attributes:
id(str): Software IDtitle(str): Software titledescription(str): Software descriptionrelease_date(date): Release dateversion(str): Software versioncategory(str): Technology categorycenter(str): NASA centerlanguage(str): Programming languagelicense(str): License informationcontact(str): Contact information
TechTransferSpinoff
Represents a NASA spinoff technology.
Attributes:
id(str): Spinoff IDtitle(str): Spinoff titledescription(str): Spinoff descriptionpublication_year(int): Publication yearcategory(str): Technology categorycenter(str): NASA centercompany(str): Company namestate(str): Statebenefits(str): Benefits descriptionapplications(str): Applications
Configuration
Environment Variables
NASA_API_KEY: Your NASA API keyNASA_API_TOKEN: Alternative name for the API key
API Key Sources (in order of precedence)
- Direct parameter:
APODClient(api_key="your_key") - Environment variable:
NASA_API_KEY - Environment variable:
NASA_API_TOKEN - Default:
DEMO_KEY(limited requests)
Error Handling
PyASAN provides comprehensive error handling:
from pyasan import APODClient
from pyasan.exceptions import (
ValidationError,
APIError,
AuthenticationError,
RateLimitError
)
client = APODClient()
try:
apod = client.get_apod(date="invalid-date")
except ValidationError as e:
print(f"Invalid input: {e}")
except AuthenticationError as e:
print(f"API key issue: {e}")
except RateLimitError as e:
print(f"Rate limit exceeded: {e}")
except APIError as e:
print(f"API error: {e}")
Development
Setup Development Environment
git clone https://github.com/yourusername/pyasan.git
cd pyasan
python -m venv venv
source venv/bin/activate # On Windows: venv\\Scripts\\activate
pip install -e ".[dev]"
Running Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=pyasan
# Run specific test file
pytest tests/test_apod.py
Code Formatting
# Format code with black
black pyasan tests
# Check with flake8
flake8 pyasan tests
# Type checking with mypy
mypy pyasan
Roadmap
- APOD API support
- Mars Rover Photos API
- TechTransfer API support
- Earth Polychromatic Imaging Camera (EPIC) API
- Near Earth Object Web Service (NeoWs)
- Exoplanet Archive API
- Image and Video Library API
- Async support
- Caching support
- Image download utilities
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- NASA for providing free access to their amazing APIs
- The astronomy community for inspiring space exploration
- All contributors who help improve this project
Links
- NASA API Portal
- APOD API Documentation
- TechTransfer API Documentation
- PyPI Package (when published)
- GitHub Repository
Made with ❤️ for the astronomy and Python communities.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyasan-0.4.4.tar.gz.
File metadata
- Download URL: pyasan-0.4.4.tar.gz
- Upload date:
- Size: 32.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0cdcd4518744ef75787a14a28844b326882cade9e383b045a27e9fc993685ea9
|
|
| MD5 |
3afd3516646326bd9a88226f8395396f
|
|
| BLAKE2b-256 |
17ea4fd1ccd101890aa36b6bec30f9f372fa1a1acb63e4d35c60cdf6687c01d4
|
File details
Details for the file pyasan-0.4.4-py3-none-any.whl.
File metadata
- Download URL: pyasan-0.4.4-py3-none-any.whl
- Upload date:
- Size: 26.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de7dbc95b7b957c1683bd705a493c6aca8636d7bcc726fac88dbba33876490e9
|
|
| MD5 |
cad7d3ffa2a52beac7a7ef51dad43f4d
|
|
| BLAKE2b-256 |
612906563a81a3967d8841325779014c025cf5f266fe06604c6f239e3caa4492
|