201.8. SSSource table¶
201.10. SSSource 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 SSSource
table and how to access it.
LSST data products: SSSource
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 SSSource
table contains single-epoch solar system source information corresponding to a specific difference image detection.
- TAP table name:
dp1.SSSource
- butler table name:
ss_source
- columns: 23
- rows: 5,988
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 packages numpy
, matplotlib
and astropy
.
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 get_tap_service
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, 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
Define the colors and symbols to represent the LSST filters in plots.
filter_names = ['u', 'g', 'r', 'i', 'z', 'y']
filter_colors = get_multiband_plot_colors()
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 SSSource
table and run the query job.
query = "SELECT column_name, datatype, description, unit " \
"FROM tap_schema.columns " \
"WHERE table_name = 'dp1.SSSource'"
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 |
diaSourceId | long | Unique identifier of the observation | |
eclipticBeta | double | Ecliptic latitude | deg |
eclipticLambda | double | Ecliptic longitude | deg |
galacticB | double | Galactic latitute | deg |
galacticL | double | Galactic longitude | deg |
heliocentricDist | float | Heliocentric distance | AU |
heliocentricVX | float | Cartesian heliocentric X velocity (at the emit time) | AU |
heliocentricVY | float | Cartesian heliocentric Y velocity (at the emit time) | AU |
heliocentricVZ | float | Cartesian heliocentric Z velocity (at the emit time) | AU |
heliocentricX | float | Cartesian heliocentric X coordinate (at the emit time) | AU |
heliocentricY | float | Cartesian heliocentric Y coordinate (at the emit time) | AU |
heliocentricZ | float | Cartesian heliocentric Z coordinate (at the emit time) | AU |
phaseAngle | float | Phase angle | deg |
residualDec | double | Residual Dec vs. ephemeris | deg |
residualRa | double | Residual R.A. vs. ephemeris | deg |
ssObjectId | long | Unique identifier of the object. | |
topocentricDist | float | Topocentric distace | AU |
topocentricVX | float | Cartesian topocentric X velocity (at the emit time) | AU |
topocentricVY | float | Cartesian topocentric Y velocity (at the emit time) | AU |
topocentricVZ | float | Cartesian topocentric Z velocity (at the emit time) | AU |
topocentricX | float | Cartesian topocentric X coordinate (at the emit time) | AU |
topocentricY | float | Cartesian topocentric Y coordinate (at the emit time) | AU |
topocentricZ | float | Cartesian topocentric Z coordinate (at the emit time) | AU |
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. Heliocentric distance¶
The cartesian heliocentric position and velocity coordinates:
heliocentricX
,heliocentricY
,heliocentricZ
,heliocentricVX
,heliocentricVY
,heliocentricVZ
The heliocentric distance:
heliocentricDist
2.2.3. Topocentric distance¶
The topocentric position and velocity coordinates:
topocentricX
,topocentricY
,topocentricZ
,topocentricVX
,topocentricVY
,topocentricVZ
The topocentric distance:
topocentricDist
2.2.4. Phase angle¶
The phase angle is the angle between the light incident onto an observed object and the light reflected from the object.
phaseAngle
2.3. Descriptions and units¶
For a subset of the key columns show the table of their descriptions and units.
col_list = set(['ssObjectId', 'heliocentricDist', 'topocentricDist', 'phaseAngle'])
tx = [i for i, item in enumerate(results['column_name']) if item in col_list]
results[tx]
column_name | datatype | description | unit |
---|---|---|---|
str64 | str64 | str512 | str64 |
heliocentricDist | float | Heliocentric distance | AU |
phaseAngle | float | Phase angle | deg |
ssObjectId | long | Unique identifier of the object. | |
topocentricDist | float | Topocentric distace | AU |
Clean up.
del col_list, tx, results
3. Data access¶
The SSSource
table is available via the TAP service and the butler.
Recommended access method: TAP.
3.1. TAP (Table Access Protocol)¶
The SSSource
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 four of the "key columns" from Section 2.3.
query = "SELECT ssObjectId, heliocentricDist, topocentricDist, phaseAngle "\
"FROM dp1.SSSource " \
"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))
5988
Option to display the table.
# results
Check if any visits had more than one source detected (with the option to print the results).
values, counts = np.unique(results['ssObjectId'], return_counts=True)
tx = np.where(counts > 1)[0]
print('Solar System objects with >1 detection: ', len(tx))
# for x in tx:
# print('ssObjectId: ', values[x], ' number of sources', counts[x])
Solar System objects with >1 detection: 417
As an example, plot a histogram of the number of sources for each object.
fig, ax = plt.subplots(figsize=(4, 4))
ax.hist(counts[tx])
plt.xlabel('Number of sources per object')
plt.tight_layout()
plt.show()
Figure 1: Histogram of the number of source detections for every Solar System object with more than one detection.
Clean up.
job.delete()
del query, results, values, counts, tx
3.1.2. Joinable tables¶
The SSSource
table can be joined to the DiaSource
table on the column containing the unique visit identifier, ssObjectId
.
The DiaSource
table contains information about the astrometric and photometric measurements for solar system objects detected in difference images.
To the query used in Section 3.2.1, add a table join to the DiaSource
table and retrieve columns midpointtMjdTai
and band
.
query = "SELECT sss.ssObjectId, sss.heliocentricDist, "\
"sss.topocentricDist, sss.phaseAngle, "\
"dia.midpointMjdTai, dia.band "\
"FROM dp1.SSSource AS sss " \
"JOIN dp1.DiaSource AS dia ON sss.ssObjectId = dia.ssObjectId " \
"WHERE dia.ssObjectId > 0"
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))
142640
Plot topocentric distance as a function of the observation midpoint of every Solar System source.
fig, ax = plt.subplots(figsize=(5, 5))
for filt in filter_names:
fx = np.where(results['band'] == filt)[0]
if len(fx) > 0:
ax.plot(results['midpointMjdTai'][fx],
results['topocentricDist'][fx],
filter_symbols[filt], ms=5, mew=0, alpha=0.7,
color=filter_colors[filt], label=filt)
plt.xlabel('midpointMjdTai')
plt.ylabel('topocentric distance (au)')
plt.legend(loc='upper left')
plt.show()
Figure 2: Topocentric distance as a function of the observation midpoint for every Solar System source, with colors and symbols to represent the five filters (ugriz) obtained on the nights of MJD = 60625 - 60658. The topocentric distance of all
SSSources
is not expected to be correlated with observation date, but rather this plot shows the 5 nights that the Low Ecliptic Latitude field were observed are obvious from the many more detections on those nights.
Clean up.
job.delete()
del query, results
3.2. Butler¶
TAP is the recommended way to access the solar system source table, but the butler can be used to retrieve the same table information.
Show that the ss_source
table has no dimensions. For DP1, it can only be retrieved from the butler in full.
butler.get_dataset_type('ss_source')
DatasetType('ss_source', {}, ArrowAstropy)
butler.get_dataset_type('ss_source').dimensions.required
{}
3.2.1. Demo query¶
Define the columns to retrieve.
col_list = ['ssObjectId', 'heliocentricDist', 'topocentricDist', 'phaseAngle']
Get the data from the butler.
results = butler.get('ss_source', parameters={'columns': col_list})
print(len(results))
5988
Option to display the results.
# results
Plot phase angle as a function of heliocentric distance for every Solar System source.
fig, ax = plt.subplots(figsize=(4, 4))
ax.scatter(results['heliocentricDist'], results['phaseAngle'], s=0.5)
plt.xlabel('Heliocentric Distance (au)')
plt.ylabel('Phase angle (deg)')
plt.tight_layout()
plt.show()
Figure 3: Phase angle as a function of heliocentric distance for every Solar System source.
Clean up.
del col_list, results