201.01. Object table#
201.1. Object 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-07-22
Repository: github.com/lsst/tutorial-notebooks
Learning objective: To understand the contents of the Object table and how to access it.
LSST data products: Object
Packages: lsst.rsp, lsst.rsp.RSPDiscovery, 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 Object table contains forced measurements in the $ugrizy$ deep_coadd images at the sky coordinates of every source detected in any individual Visit image, or in a deep_coadd image in any filter, with signal-to-noise ratio $\geq5$.
The Object table contains only deblended objects (the "children" of deblending only, no "parent" objects), and duplicates have been rejected (e.g., objects in the overlapping edges of deep_coadd images).
- TAP table name:
dp2.Object - butler table name:
object - columns: 1248
- rows: 786,420,720
Related tutorials: The TAP and Butler data access services are demonstrated in the 100-level "How to" tutorials. There is a 200-level tutorial on deep_coadd images.
1.1. Import packages¶
Import standard python packages re, numpy, matplotlib, and astropy.
From the lsst package, import modules for the TAP service and the butler.
import re
import numpy as np
import matplotlib.pyplot as plt
from lsst.rsp import RSPDiscovery
from lsst.daf.butler import Butler
1.2. Define parameters and functions¶
Instantiate RSPDiscovery with the DP2 release.
discovery = RSPDiscovery("dp2")
Instantiate the TAP service.
service = discovery.get_tap_client()
Create an instance of the Rubin data Butler.
butler = Butler('dp2', collections=["dp2"])
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 Object table and run the query job.
query = "SELECT column_name, datatype, description, unit " \
"FROM tap_schema.columns " \
"WHERE table_name = 'dp2.Object'"
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 |
| objectId | long | Unique id. Unique ObjectID | |
| tract | long | Skymap tract ID | |
| patch | long | Skymap patch ID | |
| coord_ra | double | Fiducial ICRS Right Ascension of centroid used for database indexing | deg |
| coord_dec | double | Fiducial ICRS Declination of centroid used for database indexing | deg |
| coord_raErr | float | Angular error in fiducial ICRS Right Ascension (∂RA*cos(Dec)) of centroid | deg |
| coord_decErr | float | Error in fiducial ICRS Declination of centroid | deg |
| coord_ra_dec_Cov | float | Covariance between fiducial ICRS Right Ascension (RA*cos(Dec)) and Declination of centroid | deg**2 |
| coord_flag | boolean | General Failure Flag. Reference band. | |
| refBand | char | Reference band - parameters measured on coadds of this band were used for multi-band forced photometry | |
| refExtendedness | float | Flux-ratio measure of whether an object is point-like (0) or extended (1). Reference band. | |
| refSizeExtendedness | float | Moments-based comparison of source size to the local PSF to estimate whether an object is point-like (0) or extended (1). Measured in the reference band; values range from 0 to 1. | |
| griz_model_extendedness | float | Sersic model flux- and size-based estimate of whether the object is extended (resolved) or not, from 0 (compact) to 1 (extended). Uses griz-band fluxes; values range from 0 to 1. | |
| u_ra | double | Position in right ascension, measured on u-band. | deg |
| u_dec | double | Position in declination, measured on u-band. | deg |
| u_raErr | float | Error in right ascension, measured on u-band. | deg |
| u_decErr | float | Error in declination, measured on u-band. | deg |
| u_ra_dec_Cov | float | Covariance between right ascension and declination, measured on u-band. | deg**2 |
| u_psfFlux | float | Flux derived from using the PSF model as a weight function. Forced on u-band. | nJy |
| u_psfFluxErr | float | Flux uncertainty derived from using the PSF model as a weight function. Forced on u-band. | nJy |
| u_psfMag | float | AB magnitude of the u-band psfFlux. | mag |
| u_psfMagErr | float | Uncertainty in magnitudes of the u-band psfFlux. | mag |
| ... | ... | ... | ... |
| sersic_reff_major | float | Effective radius (major axis) from the multiband Sersic model fit, prior to convolution with the PSF model (which is shrunk by 0.1 pixels in quadrature by default). | arcsec |
| sersic_reff_minor | float | Effective radius (minor axis) from the multiband Sersic model fit, prior to convolution with the PSF model (which is shrunk by 0.1 pixels in quadrature by default). | arcsec |
| sersic_theta | float | Position angle of the multiband Sersic fit ellipse. | |
| u_sersicFlux | float | u-band flux from the multiband Sersic model fit. | nJy |
| u_sersicFluxErr | float | Error on the u-band flux from the multiband Sersic model fit. | nJy |
| g_sersicFlux | float | g-band flux from the multiband Sersic model fit. | nJy |
| g_sersicFluxErr | float | Error on the g-band flux from the multiband Sersic model fit. | nJy |
| r_sersicFlux | float | r-band flux from the multiband Sersic model fit. | nJy |
| r_sersicFluxErr | float | Error on the r-band flux from the multiband Sersic model fit. | nJy |
| i_sersicFlux | float | i-band flux from the multiband Sersic model fit. | nJy |
| i_sersicFluxErr | float | Error on the i-band flux from the multiband Sersic model fit. | nJy |
| z_sersicFlux | float | z-band flux from the multiband Sersic model fit. | nJy |
| z_sersicFluxErr | float | Error on the z-band flux from the multiband Sersic model fit. | nJy |
| y_sersicFlux | float | y-band flux from the multiband Sersic model fit. | nJy |
| y_sersicFluxErr | float | Error on the y-band flux from the multiband Sersic model fit. | nJy |
| sersic_index | float | Sersic profile index parameter from the multiband Sersic model fit. | |
| sersic_indexErr | float | Error on the Sersic profile index parameter from the multiband Sersic model fit. | |
| sersic_n_eval_jac | int | Number of Jacobian evaluations for the multiband Sersic model fit. | |
| sersic_n_iter | int | Number of iterations in the non-linear fit for the multiband Sersic model. | |
| sersic_chi2_reduced | float | Reduced chi-squared of the best-fit model parameters (chi divided the number of data points) for the multiband Sersic model. | |
| sersic_unknown_flag | boolean | Flag set for failures with an unexpected or unknown cause for the multiband Sersic model. | |
| sersic_no_data_flag | boolean | Flag set when there is insufficient data to fit for the multiband Sersic model. |
The table displayed above has been truncated.
Option to print every column name as a list.
# for col in results['column_name']:
# print(col)
Option to use the regular expressions package re to find all column names that hold the psfFlux for the six filters.
# for col in results['column_name']:
# if re.fullmatch('[ugrizy]_psfFlux', col):
# print(col)
Option to search column names that contain the string temp.
# temp = 'Err'
# temp = 'pixelFlag'
# temp = 'extend'
# temp = 'cModel'
# for col in results['column_name']:
# if re.search(temp, col):
# print(col)
Delete the job, but not the results.
del query
job.delete()
2.2.2. Coordinates¶
The sky coordinates in decimal degrees for each object:
coord_ra,coord_raErrcoord_dec,coord_decErr
Per-filter coordinates in degrees are in columns [f]_ra, [f]_dec.
The all-sky tesselation regions are stored in columns tract and patch.
2.2.3. Photometry¶
Fluxes ($f$) are in nanoJanskys and can be converted to AB magnitudes ($m$) with:
$m = -2.5\log(f) + 31.4$
Magnitudes
Magnitude conversions have been done for the TAP tables, for the PSF and cModel fluxes. These columns are not available via the Butler.
[f]_psfMag,[f]_psfMagErr[f]_cModelMag,[f]_cModelMagErr
PSF fluxes
A forced fit of the Point Spread Function (PSF) at the object's coordinates in each image.
PSF fluxes are best to use for point-like sources (e.g., stars).
[f]_psfFlux,[f]_psfFluxErr
cModel fluxes
The SDSS Composite Model, the linear combination of the best fit exponential and de Vaucouleurs profile fits in each band.
The cModel fluxes are best used for extended objects (e.g., galaxies).
[f]_cModelFlux,[f]_cModelFluxErr
Other extended-object photometry measurements
[f]_sersicFlux: Sersic flux (NED documentation)[f]_gaap*: GaaP fluxes (Kuijken et al. 2008)[f]_kronFlux: Kron flux (NED documentation)[f]_ap*: aperture fluxes (radii; pixels)
Milky Way dust extinction
The value of E(B-V) at the coordinates coord_ra, coord_dec (Schlegel, Finkbeiner & Davis (1998)).
ebv
2.2.4. Shapes¶
HSM moments
Hirata-Seljak-Mandelbaum (HSM) moments (Hirata & Seljak 2003, Mandelbaum et al. 2005):
shape_xx,_yy, and_xy[f]_ixx,_iyy, and_ixy
Extendedness (star/galaxy separation)
If the product of the cModel flux and a configurable flux ratio (0.985) is less than the PSF flux, the object is "not extended" (extendedness = 0, or False).
If it is greater than the PSF flux, the object is considered "extended" (extendedness = 1, or True)
refExtendedness(extendedness in bandrefBand)[f]_extendedness(extendedness in filter[f])
2.2.5. Flags¶
Pixel flags
A variety of flags indicating whether pixels that are saturated, or affected by cosmic rays, contributed to the object's measurements.
[f]_pixelFlags_*
Measurement flags
The flux and shape measurements mentioned above have associated flag columns suffixed with _flag.
Deblending flags
If the object was deblended from a parent with more than one child, this flag is True:
detect_fromBlend
The objectId of the parent.
parentObjectId
Blendedness flag
A measure of how much the flux is affected by neighbors $1 - \frac{f_{\rm child}}{f_{\rm parent}}$. This uses the absolute value of the instrumental flux to try to obtain a de-noised value. See section 4.9.11 of Bosch et al. 2018, PASJ, 70.
[f]_blendedness
2.3. Descriptions and units¶
For a subset of the key columns show the table of their descriptions and units.
col_list = set(['objectId', 'coord_ra', 'coord_dec',
'r_psfFlux', 'r_psfFluxErr',
'r_cModelFlux', 'r_cModelFluxErr',
'r_extendedness', 'r_blendedness'])
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 |
| objectId | long | Unique id. Unique ObjectID | |
| coord_ra | double | Fiducial ICRS Right Ascension of centroid used for database indexing | deg |
| coord_dec | double | Fiducial ICRS Declination of centroid used for database indexing | deg |
| r_psfFlux | float | Flux derived from using the PSF model as a weight function. Forced on r-band. | nJy |
| r_psfFluxErr | float | Flux uncertainty derived from using the PSF model as a weight function. Forced on r-band. | nJy |
| r_extendedness | float | PSF to cModel flux-ratio measure of whether an object is point-like (0) or extended (1). Measured on r-band; values are either 0 or 1. | |
| r_blendedness | float | Measure of how much the flux is affected by neighbors, (1 - child_flux/parent_flux). Operates on the absolute value of the pixels to try to obtain a de-noised value. See section 4.9.11 of Bosch et al. 2018, PASJ, 70, S5 for details. Measured on r-band. | |
| r_cModelFlux | float | Flux from the final CModel fit. Forced on r-band. | nJy |
| r_cModelFluxErr | float | Flux uncertainty from the final CModel fit. Forced on r-band. | nJy |
Clean up.
del col_list, tx, results
3. Data access¶
The Object table is available via the TAP service and the butler.
Recommended access method: TAP.
3.1. Advisory: avoid full-table queries¶
Avoid full-table queries. Always include spatial constraints.
The Object table is a large, inclusive, union set of measurements made in the deeply coadded images at the locations of all objects detected in any image.
The DP2 data release Object table is relatively small and full-table TAP queries can run in minutes.
However, skipping spatial constraints is not a good habit to form, because future data release Object tables will contain billions of rows.
3.2. TAP (Table Access Protocol)¶
The Object table is stored in Qserv and accessible via the TAP services using ADQL queries.
Include spatial constraints:
Qserv stores catalog data sharded by coordinate (RA, Dec), so ADQL query statements that include constraints by coordinate do not requre a whole-catalog search and are typically faster (and can be much faster) than ADQL query statements which only include constraints for other columns.
Use either an ADQL cone or polygon search for faster queries (do not use WHERE ... BETWEEN statements to set boundaries on RA and Dec).
3.2.1. Demo query¶
Define a query to return the nine "key columns" from Section 2.3.
Impose spatial constraints: search within 0.2 degrees of the center of the Extended Chandra Deep Field South (ECDFS) field, RA, Dec = $53.13 -28.10$.
query = "SELECT objectId, coord_ra, coord_dec, r_extendedness, r_blendedness, " \
"r_psfMag, r_psfMagErr, r_cModelMag, r_cModelMagErr " \
"FROM dp2.Object " \
"WHERE CONTAINS(POINT('ICRS', coord_ra, coord_dec), " \
"CIRCLE('ICRS', 53.13, -28.10, 0.2)) = 1"
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))
40032
Option to display the table.
# results
As an example, plot the coordinates and the magnitude vs. the error for
objects with an r-band cModel magnitude brighter than 25.
tx = np.where(results['r_cModelMag'] <= 25.0)[0]
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(7, 3))
ax1.plot(results['coord_ra'][tx], results['coord_dec'][tx],
'o', ms=2, mew=0, alpha=0.4, color='grey')
ax1.set_xlabel('Right Ascension')
ax1.set_ylabel('Declination')
ax2.plot(results['r_cModelMag'][tx], results['r_cModelMagErr'][tx],
'o', ms=2, mew=0, alpha=0.4, color='grey')
ax2.set_xlabel('Apparent Magnitude')
ax2.set_ylabel('Error')
plt.tight_layout()
plt.show()
Figure 1: At left, the RA vs. Dec of retrieved objects is shown as a circle of grey points. At right, the r-band magnitude vs. its uncertainty shows how magnitude error increases for fainter objects.
Clean up.
job.delete()
del results
3.2.2. Joinable tables¶
The Object table can be joined to the ForcedSource table on the column objectId.
The ForcedSource table contains forced PSF photometry in the processed visit images
and difference images at the sky coordinates of every object.
The following query joins the Object and ForcedSource tables.
Columns returned include the object and forcedSource unique identifiers,
and the r-band PSF flux from the Object table.
The query is for objects that
are within 0.1 degrees of the ECDFS field center,
are not extended (are point-like), and
have an apparent magnitude $20 < r < 25$ mag.
query = "SELECT o.objectId, o.r_psfFlux " \
"FROM dp2.Object AS o " \
"JOIN dp2.ForcedSource AS fs ON o.objectId = fs.objectId " \
"WHERE CONTAINS(POINT('ICRS', o.coord_ra, o.coord_dec), " \
"CIRCLE('ICRS', 53.13, -28.10, 0.1)) = 1 " \
"AND o.refExtendedness = 0 " \
"AND o.r_psfMag > 20 AND o.r_psfMag < 25"
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))
60474
Show that this query returned data for 233 unique objects (as denoted by their objectId),
with an average of $\sim259$ forced source measurements each.
values, counts = np.unique(results['objectId'], return_counts=True)
print(len(values))
print(np.mean(counts))
233 259.5450643776824
Option to display the table.
# results
Clean up.
job.delete()
del results, values, counts
3.3. Butler¶
TAP is the recommended way to access the object table, but the Butler is a convenient way to retrieve all the objects in a given tract.
Show that the only dimension for the object table is the skymap's tract, and that it is required.
butler.get_dataset_type('object')
DatasetType('object', {skymap, tract}, ArrowAstropy)
butler.get_dataset_type('object').dimensions.required
{skymap, tract}
3.3.1. Demo query¶
Include spatial constraints:
The Butler object table contents are stored and retrieved by individual tract.
Retrieve all dataset_refs for object tables for tracts that overlap the coordinates near the center of the ECDFS field.
query = "tract.region OVERLAPS POINT(53.13, -28.10)"
refs = butler.query_datasets("object", where=query)
Show that one tract overlaps the coordinates.
for ref in refs:
print(ref.dataId)
{skymap: 'lsst_cells_v2', tract: 5063}
Define the columns to retrieve.
col_list = ['objectId', 'coord_ra', 'coord_dec',
'r_psfFlux', 'r_psfFluxErr',
'r_cModelFlux', 'r_cModelFluxErr',
'r_extendedness', 'r_blendedness']
Get the data from the butler.
results = butler.get(refs[0],
parameters={'columns': col_list})
Option to display the results.
# results
Constrain the results to non-extended objects with r-band magnitudes between 20 and 25 mag.
tx = np.where((results['r_extendedness'] == 0)
& (results['r_cModelFlux'] > 360.0)
& (results['r_cModelFlux'] <= 36000.0))[0]
print(len(tx))
30402
Plot the sky coordinates and cModel fluxes and flux errors for the subset of objects.
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(7, 3))
ax1.plot(results['coord_ra'][tx], results['coord_dec'][tx],
'o', ms=2, mew=0, alpha=0.1, color='grey')
ax1.set_xlabel('Right Ascension')
ax1.set_ylabel('Declination')
ax2.plot(-2.5 * np.log10(results['r_cModelFlux'][tx]) + 31.4,
results['r_cModelFluxErr'][tx]/results['r_cModelFlux'][tx],
'o', ms=2, mew=0, alpha=0.1, color='grey')
ax2.set_xlabel('cModel Mag')
ax2.set_ylabel('Error/Flux')
plt.tight_layout()
plt.show()
Figure 2: At left, the RA vs. Dec of retrieved objects as grey points. At right, the r-band cModel Flux vs. its uncertainty shows how flux error increases for fainter objects.
del query, refs, col_list, results, tx