201.07. SSObject table#
201.7. SSObject table¶
For the Rubin Science Platform at data.lsst.cloud.
Data Release: Data Preview 2
Container Size: Large
LSST Science Pipelines version: r30.0.10
Last verified to run: 2026-08-05
Repository: github.com/lsst/tutorial-notebooks
DOI: 10.11578/rubin/dc.20250909.20
Learning objective: To understand the contents of the SSObject table and how to access it.
LSST data products: SSObject
Packages: lsst.rsp, lsst.daf.butler, lsst.utils.plotting
Credit: Originally developed by the Rubin Community Science team. Please consider acknowledging them if this notebook is used for the preparation of journal articles, software releases, or other notebooks.
Get Support: Everyone is encouraged to ask questions or raise issues in the Support Category of the Rubin Community Forum. Rubin staff will respond to all questions posted there.
1. Introduction¶
The SSObject table contains linked Solar System objects (groupings of difference image detections). It includes the ssObjectId for each unique Solar System object and Rubin-computed per-object quantities, including the number of Rubin observations (numObs) for each Solar System object, Earth MOID (Minimum orbit intersection distance; MOIDEarth), and extendedness values derived from the corresponding DiaSources. The SSObject table also includes per band information, including number of observations, best-fit absolute magnitudes and errors, best-fit G12 slope parameters and errors, H–G12 covariance, number of data points used and Chi^2 statistic for the phase curve fit with a flag for phase curve fit failures, and minimum and maximum observed phase angles.
- TAP table name:
dp2.SSObject - butler table name:
ss_object - columns: 80
- rows: 299,343
Related tutorials: The TAP and butler data access services are demonstrated in the 100-level "How to" tutorials.
1.1. Import packages¶
Import standard python package numpy and matplotlib.
From the lsst package, import modules for the TAP service, the butler, and plotting.
import numpy as np
import matplotlib.pyplot as plt
from lsst.rsp import RSPDiscovery
from lsst.daf.butler import Butler
from lsst.utils.plotting import (get_multiband_plot_colors,
get_multiband_plot_symbols)
1.2. Define parameters and functions¶
Create an instance of the TAP service.
discovery = RSPDiscovery("dp2")
service = discovery.get_tap_client()
Create an instance of the Rubin data butler.
butler = Butler("dp2", collections="dp2")
Define the colors and symbols to represent the LSST filters in plots.
filter_colors = get_multiband_plot_colors()
filter_names = filter_colors.keys()
filter_symbols = get_multiband_plot_symbols()
2. Schema (columns)¶
To browse the table schema visit the Rubin schema browser, or use the TAP service via the Portal Aspect or as demonstrated in Section 2.1.
2.1. Retrieve table schema¶
To retrieve the table schema, define a query for the schema columns of the SSObject table and run the query job.
query = "SELECT column_name, datatype, description, unit " \
"FROM tap_schema.columns " \
"WHERE table_name = 'dp2.SSObject'"
job = service.submit_job(query)
job.run()
job.wait(phases=['COMPLETED', 'ERROR'])
print('Job phase is', job.phase)
if job.phase == 'ERROR':
job.raise_if_error()
Job phase is COMPLETED
Retrieve the query results and display them as an astropy table with the to_table() attribute.
assert job.phase == 'COMPLETED'
results = job.fetch_result().to_table()
results
| column_name | datatype | description | unit |
|---|---|---|---|
| str64 | str64 | str512 | str64 |
| r_phaseAngleMin | float | Minimum phase angle observed (r band). | deg |
| r_phaseAngleMax | float | Maximum phase angle observed (r band). | deg |
| ssObjectId | long | Unique identifier. | |
| designation | char | The unpacked primary provisional designation for this object. | |
| nObs | int | Total number of LSST observations of this object. | |
| arc | float | Timespan ("arc") of all LSST observations, t_{last} - t_{first} | d |
| firstObservationMjdTai | double | The time of the first LSST observation of this object (could be precovered), TAI. | d |
| MOIDEarth | float | Minimum orbit intersection distance to Earth. | AU |
| MOIDEarthDeltaV | float | DeltaV at the MOID point. | km/s |
| ... | ... | ... | ... |
| y_H | float | Best fit absolute magnitude (y band). | mag |
| y_HErr | float | Error in the estimate of H (y band). | mag |
| y_G12 | float | Best fit G12 slope parameter (y band). | |
| y_G12Err | float | Error in the estimate of G12 (y band). | |
| y_H_y_G12_Cov | float | H–G12 covariance (y band). | mag**2 |
| y_nObsUsed | int | The number of data points used to fit the phase curve (y band). | |
| y_Chi2 | float | Chi^2 statistic of the phase curve fit (y band). | |
| y_phaseAngleMin | float | Minimum phase angle observed (y band). | deg |
| y_phaseAngleMax | float | Maximum phase angle observed (y band). | deg |
| y_slope_fit_failed | boolean | G12 fit failed in y band. G12 contains a fiducial value used to fit H. |
The table displayed above has been truncated.
Option to print every column name as a list.
# for col in results['column_name']:
# print(col)
Delete the job, but not the results.
del query
job.delete()
2.2.2. Number of observations¶
The number of LSST observations for each Solar System object, including per band quantities:
nObs[band]_nObs
2.2.5. Extendedness¶
The minimum, median, and maximum extendedness values derived from the corresponding DiaSources:
extendednessMinextendednessMedianextendednessMax
2.2.6. Absolute magnitude¶
The best fit absolute magnitude H per band:
[band]_H
The error in the estimate of H per band:
[band]_HErr
2.2.7. Phase curve parameters¶
The best fit G12 slope parameter per band:
[band]_G12
The error in the estimate of G12 per band:
[band]_G12Err
The Chi^2 statistic of the phase curve fit per band:
[band]_Chi2
The minimum and maximum phase angles observed per band:
[band]_phaseAngleMin[band]_phaseAngleMax
3. Data access¶
The SSObject table is available via the TAP service and the butler.
Recommended access method: TAP.
3.1. TAP (Table Access Protocol)¶
The SSObject table is stored in Qserv and accessible via the TAP services using ADQL queries.
3.1.1. Catalog size¶
Retrieve the size of the current_identifications catalog.
query = "SELECT COUNT(*) "\
"FROM dp2.SSObject "
job = service.submit_job(query)
job.run()
job.wait(phases=['COMPLETED', 'ERROR'])
print('Job phase is', job.phase)
if job.phase == 'ERROR':
job.raise_if_error()
Job phase is COMPLETED
Fetch the results as an astropy table.
assert job.phase == 'COMPLETED'
results = job.fetch_result().to_table()
print(results)
COUNT1 ------ 299343
Clean up.
del query, results
job.delete()
3.1.2. Demo query¶
Define a query to return two of the key columns from Section 2.2 for the top 100 entries in the SSObject table.
To query the full SSObject table, remove "TOP 100" from the below query.
query = "SELECT TOP 100 ssObjectId, nObs "\
"FROM dp2.SSObject " \
"ORDER BY ssObjectId ASC "
job = service.submit_job(query)
job.run()
job.wait(phases=['COMPLETED', 'ERROR'])
print('Job phase is', job.phase)
if job.phase == 'ERROR':
job.raise_if_error()
Job phase is COMPLETED
Fetch the results as an astropy table and convert to a pandas dataframe.
assert job.phase == 'COMPLETED'
results = job.fetch_result()
result_df = results.to_table().to_pandas()
Option to display the results.
# result_df
Plot a histogram of the number of observations for the TOP 100 Solar System objects in the SSObject table.
fig, ax = plt.subplots(figsize=(6, 4))
ax.hist(result_df['nObs'].clip(0, 100), bins=100,
edgecolor='none', alpha=0.85)
ax.set_xlabel('Total nObs (clipped at 100)')
ax.set_ylabel('Count')
ax.set_title('Observation count for TOP 100 SSObjects')
plt.tight_layout()
plt.show()
Figure 1: Histograms of the number of observations for the TOP 100 DP2 Solar System objects in the
SSObjectstable.
Clean up.
job.delete()
del query, results, result_df
3.1.3. Joinable tables¶
The SSObject table can be joined to the SSSource table on the column ssObjectId.
The SSSource table contains single-epoch solar system source information corresponding to a specific difference image detection.
The following query joins the SSObject and SSSource tables.
Columns returned include the SSObject and SSSource unique identifiers,
the number of observations from the SSObject table,
and the heliocentric and topocentric distances from the SSSource table.
query = "SELECT TOP 100 sso.ssObjectId, sso.nObs, "\
"sss.helioRange, sss.topoRange " \
"FROM dp2.SSObject AS sso " \
"JOIN dp2.SSSource AS sss ON sso.ssObjectId = sss.ssObjectId"
job = service.submit_job(query)
job.run()
job.wait(phases=['COMPLETED', 'ERROR'])
print('Job phase is', job.phase)
if job.phase == 'ERROR':
job.raise_if_error()
Job phase is COMPLETED
Fetch the results as an astropy table and convert to a pandas dataframe.
assert job.phase == 'COMPLETED'
results = job.fetch_result()
result_df = results.to_table().to_pandas()
Option to display the results.
# result_df
Plot number of observations as a function of heliocentric and topocentric distances for the TOP 100 Solar System object sources.
fig, ax = plt.subplots(figsize=(4, 4))
ax.scatter(result_df['helioRange'], result_df['nObs'], label='Heliocentric')
ax.scatter(result_df['topoRange'], result_df['nObs'], label='Topocentric')
plt.xlabel('Distance (au)')
plt.ylabel('Number of observations')
plt.tight_layout()
plt.legend()
plt.show()
Figure 2: Number of observations versus heliocentric and topocentric distances for the TOP 100 Solar System object sources.
Clean up.
del query, results, result_df
3.2. Butler¶
TAP is the recommended way to access the solar system object table, but the butler can be used to retrieve the same table information.
3.2.1. Demo query¶
Define the columns to retrieve.
col_list = ['u_H', 'g_H', 'r_H', 'i_H', 'z_H', 'y_H']
Get the data from the butler.
results = butler.get('ss_object', parameters={'columns': col_list})
print(len(results))
299343
Option to display the results.
# results
Plot histograms of the per-band absolute magnitude ($H$) estimates, marking the median $H$-mag for each band.
fig, axes = plt.subplots(2, 3, figsize=(15, 9))
for i, b in enumerate(filter_names):
ax = axes.flat[i]
unmasked_results = results.filled(0)
h = unmasked_results[unmasked_results[f'{b}_H'] > 0][f'{b}_H']
ax.hist(h.clip(5, 28),
bins=120, color=filter_colors[b],
alpha=0.85, edgecolor='none')
ax.set_xlabel(f'{b}-band H mag')
ax.set_ylabel('Count')
ax.set_title(f'{b}-band (N={len(h):,})')
ax.axvline(np.median(h), color='0.3', linestyle='--', lw=1.2)
ax.text(0.95, 0.92, f'median = {np.median(h): .1f}',
transform=ax.transAxes, ha='right', fontsize=11,
fontstyle='italic')
plt.suptitle('Absolute Magnitude Distributions',
fontsize=15, y=1.01)
plt.tight_layout()
plt.show()
Figure 2: Histograms of the absolute magnitude ($H$) estimates per band for all DP2 Solar System objects. The median $H$-mag for each band is marked and labeled.
Clean up.
del col_list, results