102.1. Comenzando con TAP#
102.1. Comenzando con TAP¶
Para la Plataforma Científica de Rubin en data.lsst.cloud.
Divulgación de Datos: Vista Previa de Datos 2
Tamaño del contenedor (Container size): Large
Versión de las Pipelines Científicas de LSST: r30.0.11
Última verificación de ejecución: 2026-10-30
Repositorio: github.com/lsst/tutorial-notebooks
DOI: 10.11578/rubin/dc.20250909.20
Objetivo de aprendizaje: Cómo usar eficientemente el servicio TAP.
Productos de datos LSST: Tabla Object
Paquetes: lsst.rsp.RSPDiscovery
Créditos: Desarrollado originalmente por el equipo científico de la comunidad de Rubin. Por favor, considerar reconocer su trabajo si este notebook se utiliza para la preparación de artículos de revistas, lanzamientos de software u otros notebooks.
Soporte: Se invita a toda la comunidad a hacer preguntas o plantear problemas en la
Everyone is encouraged to ask questions or raise issues in the Categoría de asistencia del Foro de la Comunidad de Rubin. El equipo de Rubin responderá a todas las preguntas publicadas allí.
1. Introducción¶
El Protocolo de Acceso a Datos Tabulados TAP (Table Access Protocol) provee acceso estandarizado a los datos de los catálogos para exploración, búsqueda y recuperación. La documentación completa de TAP es proporcionada por la Alianza Internacional de Observatorios Virtuales (IVOA - International Virtual Observatory Alliance).
Este tutorial muestra cómo comenzar a utilizar el servicio TAP, explorar el esquema TAP y realizar consultas de manera eficiente.
Buenas prácticas para consultas TAP:
- Usar consultas asíncronas.
- Especificar las columnas que se desean obtener.
- Utilizar restricciones espaciales en coordenadas celestes.
- Aplicar restricciones sobre columnas (cuando corresponda).
Tutoriales relacionados: Los demás tutoriales de nivel 100 de esta serie presentan sentencias ADQL avanzadas. Los tutoriales de nivel 200 describen el contenido de los datos del catálogo e incluyen consultas de ejemplo para cada uno.
1.1. Glosario de TAP¶
- esquema - Término de bases de datos para el diseño abstracto que representa el almacenamiento de datos en una base de datos.
- esquema TAP - El conjunto de tablas que describen las tablas de datos y sus columnas.
- colección de tablas - Una colección de tablas (catálogos), por ejemplo, para una dada divulgación de datos.
- tabla - Una colección de datos relacionados almacenados en formato tabular en una base de datos.
- consulta - Una cadena formateada en ADQL que selecciona datos de una tabla, con restricciones si se desea.
- resultados - La salida del método de búsqueda del servicio TAP cuando se envía una consulta.
1.2. Sentencias ADQL¶
La documentación de ADQL incluye más información sobre sintaxis, palabras clave, operadores, funciones, etc. ADQL es similar a SQL (Structured Query Language).
Una sentencia típica de ADQL tiene al menos tres componentes:
SELECT <columnas> FROM <catálogo> WHERE <restricciones>
donde
<columnas>es una lista separada por comas de las columnas a devolver,<catálogo>es el nombre del catálogo del cual obtener los datos, y<restricciones>impone una restricción para que sólo se devuelvan las filas cuyos valores de columna cumplan las condiciones.
Por ejemplo, supongamos que existe un catálogo llamado "mysurveydata" con 5 columnas, "col1", "col2", y así sucesivamente. La sentencia ADQL:
SELECT col3, col4, col5 FROM mysurveydata WHERE col1 > 0.5 AND col5 < 10
devolvería una tabla que contiene tres columnas y todas las filas que cumplan las dos restricciones de la cláusula WHERE.
1.3. Importar paquetes¶
Importar los paquetes generales de Python
numpy y matplotlib,
y la clase RSPDiscovery para acceder al servicio TAP del RSP.
import numpy as np
import matplotlib.pylab as plt
from lsst.rsp import RSPDiscovery
2. Instanciar el servicio TAP¶
Instanciar RSPDiscovery con la divulgación de datos DP2, crear una instancia del servicio TAP y asegurarse que exista.
discovery = RSPDiscovery("dp2")
service = discovery.get_tap_client()
assert service is not None
3. Explorar el esquema TAP¶
Los esquemas TAP navegables están disponibles en sdm-schemas.lsst.io y en la interfaz de usuario de la Faceta Portal.
Esta sección muestra cómo interactuar programáticamente con el esquema TAP.
3.1. Tener precaución con las consultas síncronas¶
Una consulta "síncrona" es aquella en la que la búsqueda se ejecuta y los resultados se recuperan al mismo tiempo, y ninguna otra celda puede ejecutarse mientras la búsqueda está en curso.
Las consultas síncronas deben usarse con moderación y sólo para recuperar metadatos de tablas, como se muestra en esta sección.
Las consultas asíncronas deben utilizarse cuando se recuperan datos de tablas (Sección 4.1).
3.2. Tener precaución con SELECT *¶
Las consultas que usan SELECT *, a partir del cual se devuelven todas las columnas, sólo son apropiadas para esquemas (esta sección) o para tablas con muy pocas columnas (<20).
Las consultas que devuelven datos deben especificar cuáles de las decenas o cientos de columnas son necesarias recuperar (Sección 4.2).
3.3. Listar todos los esquemas¶
Enviar una consulta al servicio TAP para obtener los esquemas TAP y almacenar los resultados en results.
results = service.search('SELECT * FROM tap_schema.schemas')
Mostrar los resultados.
results
<DALResultsTable length=5>
schema_name utype ... schema_index
str64 str512 ... int32
----------------- ------ ... ------------
tap_schema ... 100000
dp2 ... 1
dp1 ... 2
ivoa ... 3
dp02_dc2_catalogs ... 4
El método to_table() convierte results en una tabla de Astropy.
Convertir results en una tabla y mostrarla.
results.to_table()
| schema_name | utype | description | schema_index |
|---|---|---|---|
| str64 | str512 | str512 | int32 |
| tap_schema | A TAP-standard-mandated schema to describe tablesets in a TAP 1.1 service | 100000 | |
| dp2 | Data Preview 2 (Early) contains catalog products and coadded images from the Rubin Science Pipelines v30 processing of early observations obtained with LSSTCam from April 2025 to January 2026. Coadded images and catalogs cover ~3000 square degrees; single-epoch catalogs cover ~15,000 square degrees. | 1 | |
| dp1 | Data Preview 1 contains image and catalog products from the Rubin Science Pipelines v29 processing of observations obtained with the LSST Commissioning Camera of seven ~1 square degree fields, over seven weeks in late 2024. | 2 | |
| ivoa | ObsCore v1.1 attributes in ObsTAP realization | 3 | |
| dp02_dc2_catalogs | Data Preview 0.2 contains the image and catalog products of the Rubin Science Pipelines v23 processing of the DESC Data Challenge 2 simulation, which covered 300 square degrees of the wide-fast-deep LSST survey region over 5 years. | 4 |
del results
3.4. Listar todas las tablas¶
Crear una consulta que seleccione todos los nombres de tablas del esquema TAP para DP2. Recuperar los resultados como una tabla de Astropy y mostrarla.
query = """
SELECT * FROM tap_schema.tables
WHERE tap_schema.tables.schema_name = 'dp2'
ORDER BY table_index ASC
"""
results = service.search(query).to_table()
results
| schema_name | table_name | table_type | utype | description | table_index |
|---|---|---|---|---|---|
| str512 | str64 | str8 | str512 | str512 | int32 |
| dp2 | dp2.Object | table | Descriptions of static astronomical objects (or the static aspects of variable and slowly-moving objects) detected and measured on coadds. | 10 | |
| dp2 | dp2.ForcedSource | table | Forced-photometry measurements on individual single-epoch visit images and difference images, based on and linked to the entries in the Object table. Point-source PSF photometry is performed, based on coordinates from a reference band chosen for each Object and reported in the Object.refBand column. | 30 | |
| dp2 | dp2.DiaObject | table | Properties of time-varying astronomical objects based on association of data from one or more spatially-related DiaSource detections on individual single-epoch difference images. | 40 | |
| dp2 | dp2.DiaSource | table | Properties of transient-object detections on the single-epoch difference images. | 50 | |
| dp2 | dp2.ForcedSourceOnDiaObject | table | Point-source forced-photometry measurements on individual single-epoch visit images and difference images, based on and linked to the entries in the DiaObject table. | 60 | |
| dp2 | dp2.Source | table | Properties of detections on the single-epoch visit images, performed independently of the Object detections on coadded images. | 63 | |
| dp2 | dp2.ShearObject | table | Descriptions of shear objects detected and measured on coadds with metadetection. | 66 | |
| dp2 | dp2.IsolatedStarStellarMotions | table | Position, proper motion, and parallax for isolated stars, fit using associated source measurements, with positions for associated reference objects from Gaia DR3 where available. | 68 | |
| dp2 | dp2.CoaddPatches | table | Static information about the subset of tracts and patches from the standard LSST skymap that apply to coadds in these catalogs. | 70 | |
| dp2 | dp2.Visit | table | Metadata about the pointings of the telescope, largely associated with the boresight of the LSSTComCam focal plane as a whole. | 80 | |
| dp2 | dp2.VisitDetector | table | Per-detector metadata and metrics associated with each visit. | 90 | |
| dp2 | dp2.mpc_orbits | table | Table of orbital elements and related information of known (sun-orbiting and unbound) Solar System objects. Replicated from the Minor Planet Center (Postgres) database. This schema will generally closely follow the schema of the upstream table, to allow end-users to rerun queries developed elsewhere on the RSP. | 100 | |
| dp2 | dp2.SSObject | table | LSST-computed per-object quantities. | 110 | |
| dp2 | dp2.SSSource | table | LSST-computed per-source quantities. 1::1 relationship with DiaSource. | 120 | |
| dp2 | dp2.current_identifications | table | All single-designations, and all identifications between designations. Always uses primary provisional designation (even for numbered objects). Includes all comets and satellites. Replicated from the Minor Planet Center (Postgres) database. This schema will generally closely follow the schema of the upstream table, to allow end-users to rerun queries developed elsewhere on the RSP. | 140 | |
| dp2 | dp2.numbered_identifications | table | The numbered identification table contains all the numbered objects (minor planets, comets and natural satellites) with their primary provisional designations. The table is continously updated everytime a new object is numbered. Replicated from the Minor Planet Center (Postgres) database. This schema will generally closely follow the schema of the upstream table, to allow end-users to rerun queries developed elsewhere on the RSP. | 150 |
del query, results
3.5. Listar todas las columnas¶
Crear una consulta que seleccione todos los nombres de columnas, tipos de datos, descripciones y unidades de la tabla Object de DP2. Recuperar los resultados como una tabla de Astropy.
query = """
SELECT column_name, datatype, description, unit
FROM tap_schema.columns
WHERE table_name = 'dp2.Object'
"""
results = service.search(query).to_table()
Opción para mostrar los resultados almacenados en results. La visualización de la tabla será truncada automáticamente por el notebook, ya que la tabla Object tiene 1,248 columnas.
# results
Usar un bucle for para buscar la presencia de coord en la columna
column_name de cada fila de la tabla de resultados
y escribir el nombre cuando haya una coincidencia.
search_string = 'coord'
# search_string = 'g_psfFlux'
for cname in results['column_name']:
if cname.find(search_string) > -1:
print(cname)
coord_ra coord_dec coord_raErr coord_decErr coord_ra_dec_Cov coord_flag
Descomentar la segunda línea en la celda anterior y volver a ejecutarla para imprimir todas las columnas que contengan la cadena g_psfFlux.
Imprimir el conjunto único de tipos de datos y unidades.
print(np.unique(results['datatype']))
print(np.unique(results['unit']))
datatype
--------
boolean
char
double
float
int
long
unit
--------
arcsec
d
deg
deg**2
mag
nJy
pixel
pixel**2
del query, results
4. Buenas prácticas para consultas TAP¶
Se recomienda seguir las indicaciones de esta sección al consultar y recuperar datos, ya que el servicio TAP es un recurso limitado compartido por toda la comunidad usuaria.
Este tutorial mostrará cómo realizar consultas eficientes que devuelvan sólo los datos necesarios para un análisis determinado.
La tabla Object utilizada en esta demostración contiene mediciones forzadas en las imágenes multibanda deep_coadd (coagregadas profundas) en las coordenadas de todas las detecciones con relación señal-ruido > 5 en un deep_coadd de cualquier filtro.
El tutorial de nivel 200 del catálogo Object contiene más detalles.
4.1. Usar consultas asíncronas¶
Una consulta "asíncrona" significa que la consulta se envía como un trabajo al servicio TAP y se ejecuta en segundo plano hasta completarse. Los resultados pueden recuperarse de inmediato o en un momento posterior.
El proceso general para consultas asíncronas es el siguiente:
- Definir el trabajo en la variable
jobpasando la consultaqueryal servicio TAP.
job = service.submit_job(query)
- Ejecutar el trabajo y esperar a que devuelva un resultado
COMPLETEDoERROR. La espera es opcional, pero los notebooks de tutoriales siempre esperan porque los siguientes pasos del tutorial dependen de los datos obtenidos.
job.run()
job.wait(phases=['COMPLETED', 'ERROR'])
print('La fase del trabajo es', job.phase)
- Mostrar el mensaje de error si la consulta no fue exitosa.
if job.phase == 'ERROR':
job.raise_if_error()
- Si la consulta se completó, recuperar los resultados.
assert job.phase == 'COMPLETED'
results = job.fetch_result()
4.2. Usar el Monitor de Tareas (Job Monitor)¶
Para monitorear el estado de los trabajos, abrir una nueva pestaña del "Lanzador" (Launcher) haciendo clic en el icono + en la parte superior.
Desde el menú del Lanzador, seleccionar el visor "Firefly Viewer".
Una vez que la pestaña del visor Firefly Viewer esté abierta, hacer clic en la pestaña "Job Monitor" en la parte superior. Esto mostrará los trabajos más recientes, incluyendo el título del trabajo, el ID del servicio, el tipo, la hora de inicio, la hora de finalización y la fase. La columna "Control" proporcionará opciones para ver los resultados del trabajo, inspeccionar la información del mismo (incluyendo la consulta ADQL asociada) y eliminar el trabajo.
4.3. Usar SELECT para especificar columnas¶
Las consultas de datos no deben usar SELECT *, ya que esto devolverá todas las columnas, y algunas tablas tienen miles de columnas.
Se recomienda primero decidir qué columnas son necesarias recuperar.
Usar el esquema TAP para entender las columnas disponibles.
Luego, especificar únicamente las columnas deseadas en la declaración SELECT de la consulta TAP.
4.4. Usar restricciones espaciales¶
Todas las búsquedas TAP en tablas que incluyen coordenadas celestes deben incluir restricciones espaciales.
Se recomienda comenzar siempre con restricciones espaciales para una región pequeña y luego ampliar el área de búsqueda. Las restricciones espaciales deben implementarse utilizando una búsqueda cónica o poligonal en ADQL.
Para consultas pequeñas de "exploración rápida", se recomienda usar una región espacial pequeña en lugar de simplemente limitar los resultados devueltos con TOP.
4.4.1. Fragmentación de tablas por coordenadas¶
En disco, las tablas del catálogo están fragmentadas por coordenadas (RA, Dec). Esto puede entenderse como que la base de datos está segmentada por región espacial (fragmento - shard) y distribuida en múltiples servidores. Las consultas que incluyen restricciones espaciales que minimizan el número de fragmentos que deben buscarse serán mucho más rápidas que las consultas que no tienen restricciones (o tienen restricciones muy amplias).
4.4.2. Búsquedas cónicas¶
Una búsqueda cónica es una consulta al catálogo que devuelve todos los objetos dentro de un radio determinado de una coordenada celeste. Dado que un diámetro angular determinado corresponde a un diámetro físico mayor a distancias mayores, el volumen consultado tiene forma de cono en 3D, no de cilindro.
En ADQL, una búsqueda cónica se ejecuta con WHERE CONTAINS(POINT(), CIRCLE()) = 1.
POINT()pasa las columnas del catálogo correspondientes a las coordenadas celestes.CIRCLE()define el centro y el radio del círculo de búsqueda.CONTAINS() = 1restringe la consulta para devolver únicamente las filas para las cuales la afirmación "este círculo contiene este punto" es "Verdadera" (=1).
No se recomienda aplicar restricciones sobre las columnas de coordenadas, ya sea con ADQL con una sentencia similar a -30 < coord_dec AND coord_dec < -25 o usando una cláusula WHERE ... BETWEEN, porque el servicio TAP no las interpreta de la misma manera que una búsqueda cónica o poligonal.
Crear una búsqueda cónica en la tabla Object para los objetos a distancias de 0.01 grados de las coordenadas cercanas al centro del campo ECDFS, con RA, Dec = 53, -28 grados.
query = """
SELECT coord_ra, coord_dec
FROM dp2.Object
WHERE CONTAINS(POINT('ICRS', coord_ra, coord_dec),
CIRCLE('ICRS', 53, -28, 0.01)) = 1
"""
print(query)
SELECT coord_ra, coord_dec
FROM dp2.Object
WHERE CONTAINS(POINT('ICRS', coord_ra, coord_dec),
CIRCLE('ICRS', 53, -28, 0.01)) = 1
Ejecutar la consulta de manera asíncrona y mostrar el número de filas recuperadas.
job = service.submit_job(query)
job.run()
job.wait(phases=['COMPLETED', 'ERROR'])
print('La fase del trabajo es', job.phase)
if job.phase == 'ERROR':
job.raise_if_error()
La fase del trabajo es COMPLETED
assert job.phase == 'COMPLETED'
results = job.fetch_result()
print(results)
<DALResultsTable length=106>
coord_ra coord_dec
deg deg
float64 float64
------------------ -------------------
53.00974122815018 -28.0050175995451
52.992207474582024 -27.99425087611583
52.9965043798098 -27.993613483347524
53.00147739650592 -27.993341345162747
52.99994283136329 -27.994578483538152
52.9997436002789 -27.992986558714172
52.992623866301585 -28.001834993732462
53.00544582690133 -28.000493786161528
52.996811186534444 -28.000856414669762
... ...
53.00482603163831 -27.997838568096185
53.00175529452455 -27.99944888997475
53.00234505692764 -27.99965585896137
53.003471092845786 -27.99856217031667
52.992806780233046 -27.99988157490531
52.99355705774447 -28.000673515850345
52.992369454641874 -27.998761525122774
52.9917966977763 -27.999116861955315
52.99357028146815 -27.999545246011554
Limpieza.
job.delete()
del query, results
4.4.3. Búsquedas poligonales¶
Para una búsqueda poligonal, reemplazar CIRCLE por POLYGON(ra1, dec1, ra2, dec2, ra3, dec3, ...), donde cada par ra, dec corresponde a un vértice del polígono.
4.5. Usar restricciones en columnas¶
Se recomienda comprender las columnas que se están recuperando (Sección 4.2) y, cuando corresponda, aplicar también restricciones sobre los valores de esas columnas. El objetivo es devolver únicamente las filas de la tabla que sean relevantes para el análisis (e.g., sólo los objetos de interés).
Por ejemplo, una restricción simple en una columna consiste en establecer un límite superior o inferior en sus valores, como un límite de magnitud.
Usar la misma búsqueda cónica que antes, pero ampliar el radio a $0.3$ grados y devolver únicamente los objetos de Object con una magnitud cModel en la banda $g$ más brillante que 20 mag.
query = """
SELECT coord_ra, coord_dec, g_cModelMag
FROM dp2.Object
WHERE CONTAINS(POINT('ICRS', coord_ra, coord_dec),
CIRCLE('ICRS', 53, -28, 0.3)) = 1
AND g_cModelMag < 20
"""
print(query)
SELECT coord_ra, coord_dec, g_cModelMag
FROM dp2.Object
WHERE CONTAINS(POINT('ICRS', coord_ra, coord_dec),
CIRCLE('ICRS', 53, -28, 0.3)) = 1
AND g_cModelMag < 20
job = service.submit_job(query)
job.run()
job.wait(phases=['COMPLETED', 'ERROR'])
print('La fase del trabajo es', job.phase)
if job.phase == 'ERROR':
job.raise_if_error()
La fase del trabajo es COMPLETED
assert job.phase == 'COMPLETED'
results = job.fetch_result()
print(len(results))
402
Graficar la distribución de la magnitud en la banda $g$ de los resultados obtenidos en results.
plt.hist(results['g_cModelMag'], bins=20)
plt.xlabel('g [mag]')
plt.ylabel(r'N$_{Objetos}$')
plt.show()
Figura 1: La distribución de la magnitud en la banda $g$ de los resultados obtenidos, confirmando que
resultssólo contiene objetos más brillantes que magnitud 20.
Limpieza.
job.delete()
del query, results