GCAT (General Catalog of Artificial Space Objects) is Jonathan McDowell's comprehensive catalog of all known artificial objects in space. Brahe provides functions to download and query two GCAT catalogs: SATCAT (satellite catalog) and PSATCAT (payload satellite catalog), with automatic file-based caching.
What is GCAT?
GCAT is an independent catalog maintained by astrophysicist Jonathan McDowell at the Harvard-Smithsonian Center for Astrophysics. It provides detailed metadata for every cataloged space object, including physical dimensions, orbital parameters, ownership, and mission details. Unlike the US Space Command catalog (which focuses on tracking), GCAT emphasizes comprehensive metadata about each object's identity and purpose.
The SATCAT catalog contains physical, orbital, and administrative metadata for all cataloged artificial space objects. Each record includes 42 fields organized into several categories:
The PSATCAT catalog contains payload-specific metadata for missions, extending the SATCAT with operational and registry information. Each record includes 28 fields:
Category
Fields
Description
Mission
program, class (Python: class_), category, discipline, result
importbraheasbh# Download the SATCAT catalog (cached for 24 hours by default)satcat=bh.datasets.gcat.get_satcat()print(f"Loaded {len(satcat)} SATCAT records")# Look up the ISS by NORAD SATCAT numberiss=satcat.get_by_satcat("25544")ifiss:print("\nISS (by SATCAT number 25544):")print(f" JCAT: {iss.jcat}")print(f" Name: {iss.name}")print(f" Status: {iss.status}")print(f" Perigee: {iss.perigee} km")print(f" Apogee: {iss.apogee} km")print(f" Inc: {iss.inc}°")# Look up by JCAT identifierrecord=satcat.get_by_jcat("S049652")ifrecord:print(f"\nRecord by JCAT S049652: {record.name}")# Expected output:# Loaded NNNNN SATCAT records## ISS (by SATCAT number 25544):# JCAT: S049652# Name: ISS (Zarya)# Status: O# Perigee: 408.0 km# Apogee: 418.0 km# Inc: 51.64°## Record by JCAT S049652: ISS (Zarya)
#[allow(unused_imports)]usebraheasbh;usebh::datasets::gcat;fnmain(){// Download the SATCAT catalog (cached for 24 hours by default)letsatcat=gcat::get_satcat(None).unwrap();println!("Loaded {} SATCAT records",satcat.len());// Look up the ISS by NORAD SATCAT numberifletSome(iss)=satcat.get_by_satcat("25544"){println!("\nISS (by SATCAT number 25544):");println!(" JCAT: {}",iss.jcat);println!(" Name: {}",iss.name.as_deref().unwrap_or("Unknown"));println!(" Status: {}",iss.status.as_deref().unwrap_or("Unknown"));println!(" Perigee: {} km",iss.perigee.map_or("N/A".to_string(),|v|format!("{v}")));println!(" Apogee: {} km",iss.apogee.map_or("N/A".to_string(),|v|format!("{v}")));println!(" Inc: {}°",iss.inc.map_or("N/A".to_string(),|v|format!("{v}")));}// Look up by JCAT identifierifletSome(record)=satcat.get_by_jcat("S049652"){println!("\nRecord by JCAT S049652: {}",record.name.as_deref().unwrap_or("Unknown"));}// Expected output:// Loaded NNNNN SATCAT records//// ISS (by SATCAT number 25544):// JCAT: S049652// Name: ISS (Zarya)// Status: O// Perigee: 408.0 km// Apogee: 418.0 km// Inc: 51.64°//// Record by JCAT S049652: ISS (Zarya)}
importbraheasbh# Download the SATCAT catalogsatcat=bh.datasets.gcat.get_satcat()print(f"Total records: {len(satcat)}")# Search by name (case-insensitive, searches both name and pl_name)starlink=satcat.search_by_name("starlink")print(f"\nStarlink name search: {len(starlink)} results")# Filter chaining: payloads that are operational in LEOpayloads=satcat.filter_by_type("P")print(f"\nAll payloads: {len(payloads)}")operational=payloads.filter_by_status("O")print(f"Operational payloads: {len(operational)}")leo=operational.filter_by_perigee_range(160.0,2000.0)print(f"Operational LEO payloads: {len(leo)}")# Filter by inclination range (sun-synchronous orbits ~96-99 deg)sso=operational.filter_by_inc_range(96.0,99.0)print(f"Operational SSO payloads: {len(sso)}")# Expected output:# Total records: NNNNN## Starlink name search: NNNN results## All payloads: NNNNN# Operational payloads: NNNNN# Operational LEO payloads: NNNNN# Operational SSO payloads: NNNN
#[allow(unused_imports)]usebraheasbh;usebh::datasets::gcat;fnmain(){// Download the SATCAT catalogletsatcat=gcat::get_satcat(None).unwrap();println!("Total records: {}",satcat.len());// Search by name (case-insensitive, searches both name and pl_name)letstarlink=satcat.search_by_name("starlink");println!("\nStarlink name search: {} results",starlink.len());// Filter chaining: payloads that are operational in LEOletpayloads=satcat.filter_by_type("P");println!("\nAll payloads: {}",payloads.len());letoperational=payloads.filter_by_status("O");println!("Operational payloads: {}",operational.len());letleo=operational.filter_by_perigee_range(160.0,2000.0);println!("Operational LEO payloads: {}",leo.len());// Filter by inclination range (sun-synchronous orbits ~96-99 deg)letsso=operational.filter_by_inc_range(96.0,99.0);println!("Operational SSO payloads: {}",sso.len());// Expected output:// Total records: NNNNN//// Starlink name search: NNNN results//// All payloads: NNNNN// Operational payloads: NNNNN// Operational LEO payloads: NNNNN// Operational SSO payloads: NNNN}
All filter methods return new catalog instances (immutable pattern), so the original catalog is never modified. This enables chaining multiple filters to progressively narrow results.
Both catalogs support conversion to Polars DataFrames for analysis. In Python, to_dataframe() returns a polars.DataFrame; in Rust, it returns a polars::DataFrame: