Hemos pasado el cabo de las Tormentas Objetivos ● Descubrir los principales paquetes del proyecto: imágenes, coordenadas, ... ● “Aprender a aprender” == autoaprendizaje ● Aprendizaje basado en hacer Ayudaaaaaaaaa Ayudaaaaaaaaa Ayudaaaaaaaaa www.stackoverflow.com 1. Manipulación de imágenes Manejar images El módulo para manejar imágenes es: import astropy.io.fits as fits Abrir imágenes import astropy.io.fits as fits im = fits.open('im.fits', 'readonly', memmap=False) ● ● En lugar de 'readonly', podríamos haber usado 'update'. ¡Son autoexplicativas! memmap es una opción para no cargar toda la imagen en memoria RAM, sino irla leyendo a medida que se necesite. Útil para operaciones con muchas imágenes (30? 50? 100?) ¿Qué hemos abierto? In [9]: print im [<astropy.io.fits.hdu.image.PrimaryHDU object at 0x40f4910>] En este caso im no es más que una lista de un sólo objeto. Podría haber habido varios (por ejemplo en imágenes con varias CCDs). Info sobre el objeto In [3]: im.info() Filename: cig0828_CAHA.fits No. Name 0 PRIMARY Type PrimaryHDU Cards Dimensions Format 427 (2167, 2048) float32 427 keywords en el header, dimensiones de (2167, 2048), formato float32 Datos y header datos = im[0].data header = im[0].header datos es un array de numpy header es un objeto de astropy.io.fits Datos In [16]: print [[ 314. 497. [ 315. 510. [ 317. 507. ..., [ 316. 511. [ 318. 511. [ 321. 512. datos 456. ..., 469. 468. 473.] 466. ..., 464. 469. 470.] 466. ..., 469. 468. 469.] 463. ..., 470. 472. 468.] 460. ..., 474. 466. 472.] 464. ..., 468. 470. 467.]] Header In [17]: print header SIMPLE = T / file does conform to FITS standard BITPIX = -32 / number of bits per data pixel NAXIS = 2 / number of data axes NAXIS1 = 2167 / length of data axis 1 NAXIS2 = 2048 / length of data axis 2 ... ... ... Header In [18]: print header.keys() ['SIMPLE', 'BITPIX', 'NAXIS', 'NAXIS1', 'NAXIS2', 'COMMENT', 'COMMENT', 'COMMENT', 'COMMENT', 'COMMENT', 'BLOCKED', 'BLANK', 'DATAMAX', 'DATAMIN', 'DATAMEAN', 'INSTRUME', 'TELESCOP', 'OBJECT', 'OBSERVER', 'ORIGIN', 'FILENAME', 'EXPTIME', 'DARKTIME', 'RA', 'DEC', 'HA', 'AIRMASS', 'DATE', 'LST', 'UTC', 'UT_START', 'UT_END', 'COMMENT', 'COMMENT', 'COMMENT', 'COMMENT', 'COMMENT', 'COMMENT', 'COMMENT', 'COMMENT', 'COMMENT', 'COMMENT', 'COMMENT', ...] Header In [18]: print header.values() [True, -32, 2, 2167, 2048, ' FITS (Flexible Image Transport System) format defined in Astronomy and', ' Astrophysics Supplement Series v44/p363, v44/p371, v73/p359, v73/p365.', ' Contact the NASA Science Office of Standards and Technology for the', ' FITS Definition document #100 and other FITS information.', ' 667/8', True, 32768, 65535.0, 310.0, 586.1, 'CAFOS 2.2', 'CA-2.2', 'cig 828', 'L. Verdes', 'DSAZ', 'n2_0030.fits', 120.0,...] Header In [18]: print header[“OBJECT”] “828” In [19]: print header[“exptime”] 120.0 In [20]: print header[“INSFLNAM”] rGunn Change a header In [18]: import astropy.io.fits as fits In [19]: im = fits.open("cig0828_CAHA.fits", 'update') In [20]: header = im[0].header In [21]: print header[“OBJECT”] 828 In [22]: header[“OBJECT”] = “cig 828” In [23]: im.close() Close Siempre, siempre, SIEMPRE hay que cerrar las imágenes. Es muy sencillo dejarlas abiertas ocupando memoria y haciendo quién sabe qué. im.close() Quizz He decidido que “rGunn” no es el nombre que quiero que aparezca en el filtro. ¿Entiendes el código? In In In In In [4]: [5]: [6]: [7]: [8]: import astropy.io.fits as fits im = fits.open("cig0828_CAHA.fits", 'readonly') header = im[0].header header["INSFLNAM"] = "Gunn r" im.close() Quizz He decidido que “rGunn” no es el nombre que quiero que aparezca en el filtro. ¿Entiendes el código? ¿Ves algo raro? In In In In In [4]: [5]: [6]: [7]: [8]: import astropy.io.fits as fits im = fits.open("cig0828_CAHA.fits", 'readonly') header = im[0].header header["INSFLNAM"] = "Gunn r" im.close() Writeto Para escribir una estructura es: imagen en un disco, fits.writeto(“name.fits”, data, header) la En resumen fits.open - abrir imágenes header.keys() - keywords de la cabecera? keader.values() - valores en la cabecera? im.info - información sobre la imagen im.close - cerrar imágenes fits.writeto - escribir imágenes Imágenes algo más complejas Algunas imágenes son algo más complicadas de tratar. Son las imágenes con varias extensiones. In [1]: import astropy.io.fits as fits In [2]: im = fits.open("cig0736_JKT.fits", 'update') In [3]: print im [<astropy.io.fits.hdu.image.PrimaryHDU object at 0x4586d90>, <astropy.io.fits.hdu.image.ImageHDU object at 0x4582a90>] Imágenes algo más complejas No. 0 1 Name PRIMARY Type Cards Dimensions Format PrimaryHDU 92 () ImageHDU 49 (2088, 2120) float32 La PrimaryHDU no contiene en este caso datos, es sólo una cabecera genérica de la imagen. ImageHDU contiene datos de un chip y otra cabecera, con información específica de ese chip. Millones de cosas más Estos eran los módulos más básicos. Hay muchos más, que puedes aprender usando la ayuda: help(...) - fits.getheader, fits.getdata, fits.getval, fits.update, header.add_comment, header_add_history, ... Ejercicios 1) Abre la imagen “cig0828_CAHA.fits” (readonly). Obtén el tiempo de exposición de la cabecera. Compara con usar fits.getval. 2) ¿Te acordaste de cerrar la imagen al final del ejercicio anterior? :p Ábrela de nuevo (readonly!), busca el valor del pixel (882,764) de la imagen. Compáralo con el pixel correspondiente en la imagen usando ds9. ¿Dudas? ¡Levanta la mano! 3) De la misma imagen, calcula la media, mediana, desviación estándar de los datos. Convierte en cero todos los valores por debajo de la mediana y representa esto en una imagen. Consejo: mira el help(pylab.imshow). 4) Abre la imagen “cig0828_CAHA.fits” (readonly). Abre también “masterbias_CAHA.fits”. Resta a la imagen de CIG0828 la imagen del masterbias. Graba el resultado en un nuevo archivo fits. Ejercicios 5) Ahora abre (update) la imagen resultado del ej. 3 , divídela por “masterskyflat_CAHA.fits” y ciérrala de nuevo. 6) Abre “cig0736_JKT.fits”. El objeto tiene dos extensiones, ¿cuál tiene datos? ¿y cabecera? ¿Se puede sumar las cabeceras y graba en un nuevo archivo los datos y la suma de las cabeceras? 2. Coordinates Trabajar con coordenadas Este módulo sirve para trabajar con coordenadas astronómicas import astropy.coordinates as coords Usando unidades Vamos a crear un punto con cierta RA y DEC. Usaremos para ello un módulo de unidades de astropy. In [1]: import astropy.units as u In [2]: RA = 204.2538292*u.degree In [3]: DEC = -29.8657611*u.degree In [4]: print RA 204.2538292 deg Esto lo usaremos en un segundo para otra cosa, pero me sirve de excusa para decir: ¡astropy.units es una delicia! Creando un punto Vamos a crear un punto con la RA y DEC que definimos antes y jugar un poco con ese punto. In [5]: import astropy.coordinates as coords In [6]: point1 = coords.SkyCoord(ra=RA, dec=DEC, frame='icrs') In [7]: print point1.ra, point1.dec 204d15m13.7851s -29d51m56.74s In [8]: print point1.galactic <SkyCoord (Galactic): (l, b) in deg (314.58357685, 31.97270006)> Distancia a otro punto Crearemos otro punto, y a ver qué distancia los separa. In [9]: RA2 = '13h25m27.615s' In [10]: DEC2 = "-43d1m8.80s" In [11]: point2 = coords.SkyCoord(ra=RA2, dec=DEC2) In [12]: distance = point1.separation(point2) In [13]: print distance.degree 13.3546967153 Ejercicio ¿Por qué usar coordinates cuando puedes hacer sqrt( (ra1-ra2)**2 + (dec1-dec2)**2) ? ra1, dec1 = 204.2538292*u.deg, -29.8657611*u.deg ra2, dec2 = 201.3650625*u.deg, -43.0191111111*u.deg Calcula: sqrt( (ra1 - ra2)**2 + (dec1 - dec2)**2 ) y compáralo con el resultado anterior: In [76]: print point1.separation(point2).degree 13.3546967153 Reconocer objectos por nombre ¿Quieres las coordenadas de NGC1590? coords.SkyCoord.from_name() In [14]: print coords.SkyCoord.from_name("NGC1590") <SkyCoord (ICRS): (ra, dec) in deg (67.7925208, 7.6309417)> 3. WCS (World Coordinate System) World Coordinate System Este módulo sirve para leer las coordenadas de la cabecera de la imagen, convertir de píxeles a coordenadas celestes y viceversa. import astropy.wcs as wcs Leer WCS El WCS se lee de la cabecera de la imagen import astropy.wcs as wcs import astropy.io.fits as fits im = fits.open("cig0828_CAHA.fits") w = wcs.WCS(im[0].header) De pixeles a cielo Dos módulos permiten este cambio: ● all_pix2world: mejor, más completa ● wcs_pix2world: sólo básica In [7]: print w.all_pix2world([900], [1100], 1) [array([ 266.5954571]), array([ 26.56582146])] De cielo a píxeles De nuevo, dos módulos: ● ● all_world2pix: mejor, más completa (pero más lenta si N >>>>1) wcs_world2pix: sólo básica In [7]: print w.all_world2pix([266.5954571], [26.56582146], 1) [array([ 899.99997289]), array([ 1099.99999338])] Ejercicio 1) Leer la imagen “cig0828_CAHA.fits”. Estimar en qué pixel está el centro de la galaxia. Pasar ese pixel a coordenadas en el cielo. Comparar con sus coordenadas en NED. 2) Investiga con help/internet cómo funciona w.fooprint_to_file. Abre con ds9 la imagen “cig0828_imagen2.fits” y superpon el footprint.