103.2. Protocolo para Simple Image Access SIA#
103.2. Servicio de Protocolo para Simple Image Access (SIA)¶
Para la Plataforma Científica de Rubin en data.lsst.cloud.
Divulgación de Datos: Vista Previa de Datos 1
Tamaño del contenedor (Container size): large
Versión de las Pipelines Científicas de LSST: r29.2.0
Última verificación de ejecución: 2025-02-09
Repositorio: github.com/lsst/tutorial-notebooks
DOI: 10.11578/rubin/dc.20250909.20
Objetivo de aprendizaje: Cómo usar el servicio SIA2 para acceder a datos de imágenes.
Productos de datos LSST: deep_coadd, visit_image
Paquetes: lsst.rsp.utils, lsst.rsp.service, pyvo.dal, lsst.afw.image
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 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 para Manejo de Imágenes (SIA - Simple Image Access), es un protocolo de la Alianza Internacional de Observatorios Virtuales (IVOA - International Virtual Observatory Alliance). Proporciona un modelo estandarizado para los metadatos de imágenes y la capacidad de consultar y recuperar conjuntos de datos de imágenes. Se puede obtener más información en la documentación de SIA del IVOA.
¿Por qué usar el servicio SIA?
SIA es un servicio de acceso a imágenes ampliamente utilizado y relativamente fácil para comenzar a usar.
¿Cuándo utilizar el servicio SIA?
Utilizar el servicio SIA para encontrar, recuperar y mostrar imágenes completas, basándose en su cobertura espacial, temporal y espectral. SIA es adecuado para acceder rápidamente a los datos de los píxeles y encabezados de las imágenes, para mostrarlas y examinarlas a simple vista.
Si sólo se necesita una pequeña parte de la imagen, es mejor utilizar la herramienta de recortes de imágenes.
Para casos científicos que involucran detección de fuentes o análisis de imágenes con las Pipelines Científicas de LSST (LSST Science Pipelines), se debe usar Butler para encontrar y recuperar imágenes.
En este tutorial se utiliza la versión 2 del servicio SIA (SIA2).
Tutoriales relacionados: Otros tutoriales de nivel 100 muestran cómo acceder a imágenes mediante distintos servicios, como ObsTAP y Butler. Los tutoriales de nivel 100 sobre visualización de imágenes incluyen más información sobre el uso de Firefly. Los tutoriales de nivel 200 sobre imágenes coagregadas (coadded) y de visita (visit) profundizan en estos productos de datos (por ejemplo, datos de píxeles y metadatos).
1.1. Importar paquetes¶
Importar los paquetes comunes para análisis científico numpy y astropy.
Importar los paquetes de las Pipelines Científicas de LSST (LSST Science Pipelines), para la visualización de imágenes, conversión de tipos de imagen y utilidades para el acceso remoto a datos.
Importar los paquetes de pyvo para trabajar con el servicio SIA2Service.
import numpy as np
from astropy.coordinates import SkyCoord
from astropy.time import Time
import lsst.afw.display as afwDisplay
from lsst.afw.image import ExposureF
from lsst.rsp.service import get_siav2_service
from lsst.rsp.utils import get_pyvo_auth
from pyvo.dal.adhoc import DatalinkResults
1.2. Definir parámetros y funciones¶
Definir las coordenadas de búsqueda ascensión recta (target_ra) y declinación (target_dec), en grados, para usar en todas las consultas.
Estas coordenadas están cerca del centro del campo ECDFS de DP1.
target_ra = 53.076
target_dec = -28.110
Configurar afwDisplay para usar Firefly y definir afw_display para mostrar imágenes en el frame 1.
afwDisplay.setDefaultBackend("firefly")
afw_display = afwDisplay.Display(frame=1)
2. Instanciar el servicio SIA2¶
Instanciar el servicio SIA2 y verificar que exista.
sia_service = get_siav2_service("dp1")
assert sia_service is not None
3. Consultar imágenes¶
Se recomienda restringir estrictamente las consultas de imágenes, de modo que devuelvan únicamente los productos de datos de imágenes necesarios para un análisis científico específico.
Las principales restricciones en las consultas al servicio SIA2 son:
- posición / coordenada / solapamiento de región
- tipo de imagen (nivel de calibración: cruda [raw], procesada [processed], coagregada [coadded])
- banda (filtro, cobertura espectral)
- tiempo (fecha y hora de adquisición)
Se puede encontrar una lista de todas las restricciones posibles, y sus formatos, en la documentación de SIA2Query.
3.1. Posición¶
Consulta por posición.
Realizar consultas sólo por posición no es recomendable porque devolvería todas las imágenes que se solapan con esa región, incluyendo imágenes crudas (raw), directas, diferenciales (difference) y coagregadas (coadded). Normalmente, para los análisis científicos se necesita un tipo de imagen o una banda específica, y estos deben incluirse en la consulta, como se demuestra en las secciones siguientes.
Para estos ejemplos, establecer el número máximo de registros (maxrec) en 3.
use_maxrec = 3
La posición es una región, definida como una tupla de 3, 4 o $\geq$6 elementos:
- círculo: (ra, dec, radio)
- rango: (long1, long2, lat1, lat2)
- polígono: (ra, dec, ra, dec, ra, dec, ...)
Definir pos como un círculo utilizando una tupla de ascensión recta, declinación y radio en grados.
circle = (target_ra, target_dec, 0.05)
Ejecutar la consulta SIA2.
results = sia_service.search(pos=circle, maxrec=use_maxrec)
/opt/lsst/software/stack/conda/envs/lsst-scipipe-10.1.0/lib/python3.12/site-packages/pyvo/dal/query.py:341: DALOverflowWarning: Partial result set. Potential causes MAXREC, async storage space, etc.
warn("Partial result set. Potential causes MAXREC, async storage space, etc.",
Mostrar los resultados como una tabla.
Aviso: Algunas exposiciones de ECDFS tienen erróneamente un nombre de objetivo
slew_icrs, pero en realidad pertenecen a ECDFS.
results.to_table()
| dataproduct_type | dataproduct_subtype | facility_name | calib_level | target_name | obs_id | obs_collection | obs_publisher_did | access_url | access_format | s_resolution | s_xel1 | s_xel2 | t_xel | t_min | t_max | t_exptime | t_resolution | em_xel | em_min | em_max | em_res_power | em_filter_name | o_ucd | pol_xel | instrument_name | lsst_visit | lsst_detector | lsst_tract | lsst_patch | lsst_band | lsst_filter | obs_title | s_ra | s_dec | s_fov | s_region |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| arcsec | d | d | s | s | m | m | deg | deg | deg | |||||||||||||||||||||||||||
| object | object | object | int32 | object | object | object | object | object | object | float64 | int64 | int64 | int64 | float64 | float64 | float64 | float64 | int64 | float64 | float64 | float64 | object | object | int64 | object | int64 | int64 | int64 | int64 | object | object | object | float64 | float64 | float64 | object |
| image | lsst.raw | Rubin:Simonyi | 1 | slew_icrs | CC_O_20241108_000266 | LSST.DP1 | ivo://org.rubinobs/usdac/lsst-dp1?repo=dp1&id=c9b72b48-0087-57a6-bd0c-2120836aedd4 | https://data.lsst.cloud/api/datalink/links?ID=ivo%3A%2F%2Forg.rubinobs%2Flsst-dp1%3Frepo%3Ddp1%26id%3Dc9b72b48-0087-57a6-bd0c-2120836aedd4 | application/x-votable+xml;content=datalink | -- | 4608 | 4096 | -- | 60623.27366114595 | 60623.27401335648 | 30.0 | -- | -- | 4.026e-07 | 5.483e-07 | -- | g | phot.count | -- | LSSTComCam | 2024110800266 | 0 | -- | -- | g | g_01 | raw - g - CC_O_20241108_000266-R22_S00 2024-11-09T06:34:04.323010Z | 52.99197077057104 | -28.11438844236187 | 0.3179712897409338 | POLYGON ICRS 52.898024 -27.978909 52.839871 -28.199792 53.086238 -28.249758 53.143786 -28.028839 |
| image | lsst.raw | Rubin:Simonyi | 1 | slew_icrs | CC_O_20241108_000270 | LSST.DP1 | ivo://org.rubinobs/usdac/lsst-dp1?repo=dp1&id=041a0fb4-7358-5457-bcde-e453ef64d554 | https://data.lsst.cloud/api/datalink/links?ID=ivo%3A%2F%2Forg.rubinobs%2Flsst-dp1%3Frepo%3Ddp1%26id%3D041a0fb4-7358-5457-bcde-e453ef64d554 | application/x-votable+xml;content=datalink | -- | 4608 | 4096 | -- | 60623.28061678261 | 60623.280969085645 | 30.0 | -- | -- | 4.026e-07 | 5.483e-07 | -- | g | phot.count | -- | LSSTComCam | 2024110800270 | 0 | -- | -- | g | g_01 | raw - g - CC_O_20241108_000270-R22_S00 2024-11-09T06:44:05.290018Z | 52.909077390196416 | -28.180548573758742 | 0.3179909938756991 | POLYGON ICRS 52.815074 -28.045065 52.756875 -28.265958 53.003408 -28.315918 53.060993 -28.094997 |
| image | lsst.raw | Rubin:Simonyi | 1 | slew_icrs | CC_O_20241108_000274 | LSST.DP1 | ivo://org.rubinobs/usdac/lsst-dp1?repo=dp1&id=f1c33d01-37b6-5ba3-83e7-78b403bd7985 | https://data.lsst.cloud/api/datalink/links?ID=ivo%3A%2F%2Forg.rubinobs%2Flsst-dp1%3Frepo%3Ddp1%26id%3Df1c33d01-37b6-5ba3-83e7-78b403bd7985 | application/x-votable+xml;content=datalink | -- | 4608 | 4096 | -- | 60623.28380763904 | 60623.28415983796 | 30.0 | -- | -- | 4.026e-07 | 5.483e-07 | -- | g | phot.count | -- | LSSTComCam | 2024110800274 | 0 | -- | -- | g | g_01 | raw - g - CC_O_20241108_000274-R22_S00 2024-11-09T06:48:40.980013Z | 52.90653061685272 | -28.044048182264174 | 0.3179661367732995 | POLYGON ICRS 52.812634 -27.908564 52.754536 -28.129455 53.000743 -28.179420 53.058246 -27.958502 |
Conservar circle para reutilizarlo más adelante, pero eliminar results.
del results
Opción para pasar las coordenadas al servicio SIA2 como un objeto SkyCoord de astropy.
# coord = SkyCoord(target_ra, target_dec, unit="deg")
# coord_circle = (coord, 0.05)
# results = sia_service.search(pos=coord_circle, maxrec=use_maxrec)
# results.to_table()
# del coord, coord_circle, results
Opción para definir los límites de búsqueda como coordenadas máximas y mínimas.
# bounds = (target_ra-0.05, target_ra+0.05, target_dec-0.05, target_dec+0.05)
# results = sia_service.search(pos=bounds, maxrec=use_maxrec)
# results.to_table()
# del bounds, results
Opción para definir un polígono con cuatro puntos.
# polygon = (target_ra-0.05, target_dec-0.05,
# target_ra+0.05, target_dec-0.05,
# target_ra+0.05, target_dec+0.05,
# target_ra-0.05, target_dec+0.05)
# results = sia_service.search(pos=polygon, maxrec=use_maxrec)
# results.to_table()
# del polygon, results
3.2. Tipo de imagen¶
Realizar una consulta por tipo de imagen, que en el servicio SIA2 se especifica mediante el nivel de calibración (calib_level)
y mediante el subtipo de producto de datos (dpsubtype).
Los nombres de los niveles de calibración y subtipos de producto de datos son:
- 1 :
raw: para imágenes crudas. - 2 :
visit_image: para imágenes de visita. - 3 :
deep_coadd,template_coadd,difference_image: para imágenes coagregadas profundas, para imágenes de referencia y para imágenes diferenciales, respectivamente.
3.2.1. Imágenes de visita¶
Realizar una consulta para imágenes de visita visit_image estableciendo el nivel de calibración calib_level=2 O el subtipo de producto de datos dpsubtype='lsst.visit_image',
ya que sólo existe un subtipo de producto de datos (visit_image) para el nivel de calibración 2.
Devolver los resultados como tablas de Astropy usando .to_table().
Establecer el nivel de calibración con calib_level.
results = sia_service.search(pos=circle, calib_level=2).to_table()
print(len(results))
1656
Opción para repetir la consulta estableciendo dpsubtype para confirmar que devuelven el mismo número de visit_images.
# results = sia_service.search(pos=circle, dpsubtype='lsst.visit_image').to_table()
# print(len(results))
Opción para mostrar la tabla de resultados, que se mostrará truncada.
# results
del results
3.2.2. Imágenes coagregadas profundas¶
Realizar una consulta para imágenes coagregadas profundas deep_coadd configurando el nivel de calibración calib_level=3 y el subtipo de producto de datosdpsubtype='lsst.deep_coadd'.
No utilizar use_maxrec aquí; recuperar todas las imágenes deep_coadd que cumplan con las restricciones de búsqueda.
results = sia_service.search(pos=circle, calib_level=3, dpsubtype='lsst.deep_coadd').to_table()
print(len(results))
12
Opción para mostrar la tabla completa de resultados.
# results
Imprimir el número de valores únicos de lsst_band (filtros).
values, counts = np.unique(results['lsst_band'],
return_counts=True)
for value, count in zip(values, counts):
print(value, count)
g 2 i 2 r 2 u 2 y 2 z 2
Hay 2 parcelas (patches) superpuestas para las coordenadas de búsqueda y, por lo tanto, 2 imágenes deep_coadd para cada uno de los seis filtros.
del results, values, counts
3.2.3. Imágenes de referencia coagregadas¶
Realizar una consulta para imágenes de referencia coagregadas template_coadd estableciendo el nivel de calibración calib_level=3 y el subtipo de producto de datos dpsubtype='lsst.template_coadd'.
Dado que las imágenes template_coadd también se almacenan por parcela (patch), también hay 12 que coinciden con las restricciones de la consulta.
results = sia_service.search(pos=circle, calib_level=3, dpsubtype='lsst.template_coadd')
print(len(results))
12
del results
3.2.4. Imágenes diferenciales¶
Realizar una consulta para imágenes diferenciales difference_image estableciendo el nivel de calibración calib_level=3 y el subtipo de producto de datos dpsubtype='lsst.difference_image'.
Se devolverán tantas imágenes diferenciales como imágenes de visita visit_image existan.
results = sia_service.search(pos=circle, calib_level=3, dpsubtype='lsst.difference_image')
print(len(results))
1656
del results
3.3. Banda¶
Consultar por banda.
Con el servicio SIA2, band no es la letra del nombre de un filtro, sino un rango de longitudes de onda (en metros).
Para LSST, las curvas de transmisión de los filtros apenas se superponen y estos valores pueden utilizarse como los “límites” de la banda.
band_edges = {'u': (3.000e-07, 3.932e-07),
'g': (4.026e-07, 5.483e-07),
'r': (5.510e-07, 6.891e-07),
'i': (6.936e-07, 8.188e-07),
'z': (8.192e-07, 9.201e-07),
'y': (9.278e-07, 1.100e-06)}
Definir la banda band que se le pasará al servicio SIA2.
Usar el extremo inferior de la banda $r$ de LSST y el extremo superior de la banda $i$ de LSST,
para recuperar tanto las imágenes en banda $r$ como en banda $i$.
band = (band_edges['r'][0], band_edges['i'][1])
print(band)
(5.51e-07, 8.188e-07)
Consultar el servicio SIA2 y convertir los resultados a una tabla de astropy.
results = sia_service.search(pos=circle, band=band, calib_level=2)
table = results.to_table()
Imprimir la cantidad de imágenes en bandas $r$ e $i$ que se devolvieron.
values, counts = np.unique(table['lsst_band'], return_counts=True)
for value, count in zip(values, counts):
print(value, count)
del values, counts
i 321 r 466
del results, table
Alternativamente, definir una única longitud de onda (5e-07 m está en la banda $g$) y el servicio SIA2 devolverá todas las imágenes cuyo filtro se superponga con esa longitud de onda.
results = sia_service.search(pos=circle, band=(5e-07), calib_level=2)
print(len(results))
414
del band, results
3.4. Tiempo¶
La fecha y hora de adquisición de las imágenes sólo pueden limitarse para imágenes raw y visit_image (niveles de calibración 1 y 2).
Definir time1 y time2 usando Time de astropy.
Utilizar el Tiempo Atómico Internacional (Temps Atomique International; TAI) para definir tiempos de astropy, ya que las horas de adquisición de las imágenes de Rubin se almacenan como tiempos TAI. Los tiempos pueden definirse como fechas del calendario o como MJD, como en time1 y time2 a continuación.
time1 = Time("2024-11-09T00:00:00.0", format="isot", scale="tai")
time2 = Time(60624.0, format="mjd", scale="tai")
Consultar por imágenes visit_image que se superpongan con circle y que hayan sido obtenidas entre time1 y time2.
La longitud de la tabla de resultados debería ser 131.
results = sia_service.search(pos=circle, calib_level=2,
time=(time1, time2))
print(len(results))
131
Opción para mostrar la tabla de resultados.
# results.to_table()
Eliminar las restricciones de la consulta, pero conservar la tabla de resultados para usarla en la Sección 4.
del time1, time2
4. Recuperar y mostrar una imagen¶
Usar los resultados almacenados en results de la consulta de la Sección 3.4.
Extraer la URL de acceso de la primera fila de los resultados y almacenarla en datalink_url.
Recuperar el documento VOTable del enlace de datos o datalink y almacenarlo en dl_result. En este punto, el servicio requiere credenciales de autorización, que se pasan con la función utilitaria get_pyvo_auth() del paquete lsst.rsp.
Obtener la URL de la imagen específica como image_url.
datalink_url = results[0].access_url
dl_result = DatalinkResults.from_result_url(datalink_url, session=get_pyvo_auth())
image_url = dl_result.getrecord(0).get('access_url')
Opción para mostrar las URLs.
# datalink_url
# dl_result
# image_url
Leer la imagen completa en un objeto ExposureF. El formato ExposureF está diseñado para funcionar sin problemas con afw.display y, por lo tanto, se recomienda para todas las imágenes de Rubin.
visit_image = ExposureF(image_url)
Mostrar la exposición en la pestaña de Firefly.
afw_display.mtv(visit_image)
Configurar la transparencia de la máscara al 100% (totalmente transparente).
afw_display.setMaskTransparency(100)
5. Ejercicios¶
Las coordenadas centrales aproximadas del campo Rubin_SV_95_-25 para la Vista Previa de Datos 1 (Data Preview 1) son RA, Dec = $95, -25$.
Mostrar que el número de imágenes de visita visit_image obtenidas en MJD 60634 que se superponen con estas coordenadas es 43.