201.7. SSObject table¶
201.7. SSObject table¶
Data Release: Data Preview 1
Container Size: large
LSST Science Pipelines version: r29.1.1
Last verified to run: 2025-06-20
Repository: github.com/lsst/tutorial-notebooks
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
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, the number of LSST observations, numObs
, for each Solar System object, and the date the LSST first linked and submitted the discovery observations to the MPC, which may be NULL if the object is not an LSST discovery.
- TAP table name:
dp1.SSObject
- butler table name:
ss_object
- columns: 3
- rows: 431
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
.
From the lsst
package, import modules for the TAP service and the butler.
import numpy as np
import matplotlib.pyplot as plt
from lsst.rsp import get_tap_service
from lsst.daf.butler import Butler
1.2. Define parameters and functions¶
Create an instance of the TAP service, and assert that it exists.
service = get_tap_service("tap")
assert service is not None
Create an instance of the Rubin data butler, and assert that it exists.
butler = Butler('dp1', collections="LSSTComCam/DP1")
assert butler is not None
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 = 'dp1.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 |
discoverySubmissionDate | double | The date the LSST first linked and submitted the discovery observations to the MPC. May be NULL if not an LSST discovery. The date format will follow general LSST conventions (MJD TAI, at the moment). | d |
numObs | int | Number of LSST observations of this object | |
ssObjectId | long | Unique identifier. |
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.3. Discovery submission date¶
The date the LSST first linked and submitted the discovery observations to the MPC:
discoverySubmissionDate
This value may be NULL if the object is not an LSST discovery. The date format will follow general LSST conventions (MJD TAI, at the moment).
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. Demo query¶
Define a query to return the three columns from Section 2.3.
query = "SELECT ssObjectId, numObs, discoverySubmissionDate "\
"FROM dp1.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.
assert job.phase == 'COMPLETED'
results = job.fetch_result().to_table()
print(len(results))
431
Option to display the table.
# results
job.delete()
del results
3.1.2. 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 sso.ssObjectId, sso.numObs, "\
"sss.heliocentricDist, sss.topocentricDist " \
"FROM dp1.SSObject AS sso " \
"JOIN dp1.SSSource AS sss ON sso.ssObjectId = sss.ssObjectId " \
"ORDER BY sso.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
assert job.phase == 'COMPLETED'
results = job.fetch_result().to_table()
print(len(results))
5988
Show that this query returned data for 431 unique objects, with an average of $\sim14$ source measurements each.
values, counts = np.unique(results['ssObjectId'], return_counts=True)
print(len(values))
print(np.mean(counts))
431 13.893271461716937
Option to display the table.
# results
Plot histograms of the heliocentric and topocentric distances for all Solar System object sources.
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 4))
ax1.hist(results['heliocentricDist'])
ax2.hist(results['topocentricDist'])
ax1.set_xlabel('Heliocentric distances of object detections (au)')
ax2.set_xlabel('Topocentric distances of object detections (au)')
plt.show()
Figure 1: Histograms of the heliocentric and topocentric distances for all Solar System object sources.
Clean up.
job.delete()
del results, values, counts
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.
Show that the ss_object
table has no dimensions. For DP1, it can only be retrieved from the butler in full.
butler.get_dataset_type('ss_object')
DatasetType('ss_object', {}, ArrowAstropy)
butler.get_dataset_type('ss_object').dimensions.required
{}
3.2.1. Demo query¶
Define the columns to retrieve.
col_list = ['ssObjectId', 'numObs', 'discoverySubmissionDate']
Get the data from the butler.
results = butler.get('ss_object', parameters={'columns': col_list})
print(len(results))
431
Option to display the results.
# results
As an example, plot a histogram of the number of sources for each object.
fig, ax = plt.subplots(figsize=(4, 4))
ax.hist(results['numObs'])
plt.xlabel('Number of sources per object')
plt.tight_layout()
plt.show()
Figure 2: Histogram of the number of source detections for every Solar System object with more than one detection.
Clean up.
del col_list, results