Segunda parte (Python): API APOD de la NASA

Autores/as

Brenda Poulette Torres Vargas

Diego Betancourt Peralta

Erick Iván Canul Hernández

José Omar Gutiérrez Gutiérrez

Maximiliano Hernández Pérez

Instrucciones

  • Usarán la API de la NASA llamada APOD (Astronomy Picture of the Day). Busca su documentación en https://api.nasa.gov/
  • Genera una API key en el sitio https://api.nasa.gov/
  • Cada miembro del equipo debe seleccionar la palabra correspondiente al número de la primera letra de tu apellido paterno. Por ejemplo, 1 = A, 2 = B, 3 = C, etc. Si tu apellido empieza con Ñ, selecciona la última palabra de la lista. Si la palabra coincide con la de algunos miembro de tu equipo, toma la inmediata posterior.
  1. gravitational
  2. retrograde
  3. supernova
  4. spiral
  5. James Webb
  6. emission
  7. nebula
  8. planetary
  9. Juno
  10. X-ray
  11. black hole
  12. infrared
  13. dust clouds
  14. aurora borealis
  15. Northern Lights
  16. geomagnetic storm
  17. Perseids
  18. Geminids
  19. Einstein
  20. elliptical
  21. Newton
  22. Spitzer
  23. Kepler
  24. Apollo
  25. Voyager
  26. Redshift
  27. Hand of God
  28. Hydrogen
  29. alpha
  30. Sulfur
  • Cuidado: La API se puede sentir “atacada” y bloquearte si haces muchas solicitudes rápidamente.
  • Cuidado: La API sólo permite un número finito de solicitudes.

Basándose en solicitudes de la API en el campo “explanation” haz búsquedas basadas en tu palabra y responde la siguientes preguntas:

Preguntas del equipo:

  1. ¿Qué tipo de parámetros admite la solicitud?
  2. ¿Qué tipo respuestas se pueden obtener con cada solicitud?
  3. ¿Qué tipo de restricciones tiene la API?

Preguntas de cada miembro del equipo:

  1. Para las búsquedas de tu palabra, ¿cuántos resultados obtuviste?
  2. Para las búsquedas de tu palabra, ¿en qué rangos de fechas se introdujo el recurso?
  3. Para las búsquedas de tu palabra, ¿cuáles son los “media_type” más comunes?
  4. Para las búsquedas de tu palabra, ¿quiénes son los autores o instituciones propietaria de los derechos (i.e. el copyright)?

Preguntas del equipo

1. ¿Qué tipo de parámetros admite la solicitud?

La API APOD de la NASA admite los siguientes parámetros en las solicitudes:

  • api_key (string) - La clave generada para uso ampliado. Por defecto es DEMO_KEY.
  • date (string) - Una cadena en formato YYYY-MM-DD que indica la fecha de la imagen APOD a recuperar. Debe ser posterior al 16 de junio de 1995 (1995-06-16), fecha en que se publicó por primera vez una imagen de APOD. No hay imágenes disponibles para mañana a través de esta API. Por defecto es la fecha de hoy.
  • start_date (string) - Una cadena en formato YYYY-MM-DD que indica el inicio de un rango de fechas. Todas las imágenes comprendidas entre start_date y end_date se devolverán en un JSON array. No se puede usar con date. El valor por defecto es None.
  • end_date (string) - Una cadena en formato YYYY-MM-DD que indica el final de un rango de fechas. Si se especifica start_date sin end_date, end_date toma por defecto la fecha actual.
  • count (int) - Un número entero positivo, no mayor que 100. Si se especifica, se devolverá la cantidad de imágenes elegidas aleatoriamente en un JSON array. No se puede usar junto con date ni con start_date y end_date. El valor por defecto es None.
  • thumbs (bool) - Un booleano True|False que indica si la API debe devolver la URL de la imagen en miniatura para los archivos de video. Si se establece en True, la API devuelve la URL de la miniatura del video. Si un APOD no es un video, este parámetro se ignora. El valor por defecto es False.
  • hd (bool) - Un booleano True|False que indica si se deben devolver imágenes de alta resolución. Este parámetro se incluye por motivos de compatibilidad con versiones anteriores; el servicio siempre lo ignora y, en cualquier caso, se devuelven las URL de alta resolución.
  • concept_tags (bool) - Un booleano True|False que indica si las etiquetas de concepto deben incluirse en la respuesta. Estas etiquetas no necesariamente se incluyen en la explicación, sino que se derivan de etiquetas de búsqueda comunes asociadas al texto de la descripción. (Mejor que una simple búsqueda de texto). El valor por defecto es False. Por ahora, este parámetro está deshabilitado en este servicio.

2. ¿Qué tipo respuestas se pueden obtener con cada solicitud?

La estructura de la respuesta depende de los parámetros utilizados en cada solicitud:

  • Si solicitas la imagen de hoy o una fecha específica con date, la API devolverá un único objeto JSON (un diccionario en Python).
  • Si solicitas todas las imágenes comprendidas en un rango de fechas con start_date y end_date, la API devolverá una lista de objetos JSON, uno por cada día del periodo solicitado.
  • Si solicitas un número de imágenes seleccionadas al azar con count, la API devolverá una lista de objetos JSON, uno por cada día seleccionado al azar.

Cada objeto JSON contiene metadatos sobre la Astronomy Picture of the Day (APOD) del día especificado.

Los campos principales del objeto JSON son los siguientes:

  • title - El título de la imagen.
  • date - Fecha de la imagen.
  • url - La URL de la imagen o el video APOD del día.
  • explanation - El texto que explica la imagen.
  • hdurl - La URL de la imagen del día en alta resolución.
  • media_type - El tipo de medio (datos) devuelto. Puede ser image o video según el contenido.
  • service_version - Versión del servicio utilizada.

Opcionales:

  • copyright - Nombre del titular de los derechos de autor. Sólo se devuelve si la imagen no es de dominio público.
  • thumbnail_url - La URL de la miniatura del vídeo. Sólo se devuelve si el tipo de medio es un video y si thumbs = True

No disponibles en este servicio:

  • resource
  • concept_tags
  • concepts

Además, la API devuelve un código de estado que indica si la solicitud fue exitosa o no, los más comunes son:

  • 200 OK: La solicitud fue exitosa y el servidor devolvió lo que se solicitó.
  • 400 Bad Request (Solicitud incorrecta): La solicitud estaba mal formada y el servidor no pudo entenderla. Ocurre cuando hay un error en los parámetros.
  • 403 Forbidden (Prohibido): La solicitud está prohibida y el cliente no está autorizado para acceder al recurso. Ocurre si se proporcionó una API Key no válida.
  • 404 Not Found (No encontrado): El recurso solicitado no existe (por ejemplo, no hay datos disponibles para la fecha de mañana).
  • 429 Too Many Requests (Demasiadas solicitudes): Superaste el límite de solicitudes (Over Rate Limit). En este caso, ocurre al superar las 1,000 solicitudes por hora con la API key.
  • 500 Internal Server Error (Error interno del servidor): Ocurrió un error inesperado en el servidor de la NASA.
  • 503 Service Unavailable (Servicio No disponible): Indica que el servidor web está temporalmente inhabilitado para procesar solicitudes, generalmente por sobrecarga o mantenimiento.

3. ¿Qué tipo de restricciones tiene la API?

La API tiene límites establecidos en la cantidad de solicitudes que puedes realizar:

  • Utilizando una API key propia, el límite es de 1000 solicitudes por hora. Si excedes este límite, tu API key será bloqueada temporalmente y no podrás realizar más solicitudes. El bloqueo se levantará automáticamente tras una hora.
  • Utilizando la DEMO_KEY, el límite de uso es de 30 solicitudes por dirección IP por hora con un máximo de 50 solicitudes por dirección IP al día.

Tiene restricciones con las fechas que puedes solicitar:

  • No puedes solicitar información anterior al 16 de junio de 1995, fecha en la que inició el servicio APOD.
  • Tampoco puedes solicitar información de fechas futuras como “mañana”, la API solo responde con datos hasta la fecha de hoy.

Tiene restricciones con las combinaciones de parámetros que puedes realizar en una solicitud:

  • Si usas el parámetro date (para obtener una imagen específica), no puedes usar count, start_date ni end_date.
  • Si usas el parámetro count (para obtener imágenes al azar), no puedes usar date, start_date ni end_date.
  • Si usas los parámetros start_date y end_date (para obtener todas las imágenes en un rango de fechas), no puedes usar date ni count.
  • No puedes usar el parámetro end_date sin usar start_date.

Tiene restricciones con el tamaño de las solicitudes y la frecuencia de las mismas:

  • Si el rango de fechas en la solicitud es demasiado grande, la respuesta podría fallar por tiempo de espera.
  • Si realizas muchas solicitudes simultáneas se podría saturar el servicio y provocar un error en la respuesta.

Datos

Usaremos la API de la NASA llamada APOD (Astronomy Picture of the Day).

Documentación en https://api.nasa.gov/

Cargar librerías

import requests
import pandas as pd
import time
from datetime import datetime

Guarda tu API key generada en el sitio https://api.nasa.gov/

Vamos a cargar la API key desde el archivo .env:

from dotenv import load_dotenv
import os

load_dotenv()
True
mi_api_key = os.getenv("NASA_API_KEY")

Para empezar, veamos como realizar una solicitud simple a la API APOD de la NASA.

# Establecer API key y URL para la solicitud
api_key = mi_api_key
url = 'https://api.nasa.gov/planetary/apod'

# Establecer fechas para realizar la solicitud
start_date = '2026-03-16'
end_date = '2026-04-16'

# Establecer los parámetros de la solicitud
obs_params = {
    'api_key': api_key,
    'start_date': start_date,
    'end_date': end_date
}

response = requests.get(url, params = obs_params)

Revisemos la respuesta recibida.

response
<Response [200]>

Tipo de respuesta 200 significa éxito.

Guardar los registros en un DataFrame mi_df

mi_data = response.json()
mi_df = pd.DataFrame(mi_data)

Explorar el Dataframe mi_df

mi_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 32 entries, 0 to 31
Data columns (total 8 columns):
 #   Column           Non-Null Count  Dtype 
---  ------           --------------  ----- 
 0   date             32 non-null     object
 1   explanation      32 non-null     object
 2   hdurl            28 non-null     object
 3   media_type       32 non-null     object
 4   service_version  32 non-null     object
 5   title            32 non-null     object
 6   url              32 non-null     object
 7   copyright        19 non-null     object
dtypes: object(8)
memory usage: 2.1+ KB

Imprimimos el dataframe desde R para poder explorarlo más fácilmente:

py$mi_df

Listo, hemos realizado una solicitud exitosa.

Cargar la base api_pod_data.csv

Para fines de practicidad y evitar tener que descargar todos los registros de la API APOD en cada ejecución del script, hemos tomado la decisión de descargar todos los registros comprendidos desde el 16 de junio de 1995 (primer registro de la API) hasta el 16 de mayo de 2026. La base se ha guardado en un archivo csv llamado api_apod_data.csv.

# Para leer y guardar el csv en un nuevo DataFrame
df_apod =  pd.read_csv('../datos/api_apod_data.csv', sep=';')
# Rango de fechas del CSV
print(df_apod['date'].min())
1995-06-16
print(df_apod['date'].max())
2026-05-16
df_apod.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 11288 entries, 0 to 11287
Data columns (total 8 columns):
 #   Column           Non-Null Count  Dtype 
---  ------           --------------  ----- 
 0   date             11288 non-null  object
 1   explanation      11272 non-null  object
 2   hdurl            10862 non-null  object
 3   media_type       11288 non-null  object
 4   service_version  11288 non-null  object
 5   title            11288 non-null  object
 6   url              11263 non-null  object
 7   copyright        5564 non-null   object
dtypes: object(8)
memory usage: 705.6+ KB
# Imprimimos con R
py$df_apod

Código para descargar todos los registros de la API

A continuación, mostramos el código que hemos utilizado para descargar todos los registros de la API APOD.

El código consiste en un ciclo for que realiza solicitudes mes por mes a la API para el periodo de tiempo deseado.

Realiza solicitudes relativamente pequeñas (un mes) para evitar saturar el servicio y provocar un error en la respuesta.

Además, hemos añadido una pausa time.sleep(2) para no realizar muchas solicitudes rápidamente y evitar que sea bloqueada nuestra API key.

Devuelve un DataFrame llamado df_registros que almacena todos los registros de la API APOD comprendidos en el rango establecido entre fecha_inicio y fecha_final.

Nota importante: El tiempo estimado de ejecución es de aproximadamente 30 minutos debido a las pausas obligatorias de la API y a las dimensiones de la misma. Hemos añadido la opción de chunk #| eval: false para que los chunks no se ejecuten cuando renderizamos el archivo.

# ¡ATENCIÓN! Tiempo estimado de ejecución: ~30 minutos.
# Capturar todos los registros por mes (372 consultas hasta mayo 2026)

# Establecer API key y URL para cada solicitud
api_key = mi_api_key
url = 'https://api.nasa.gov/planetary/apod'

# Lista vacía para almacenar los registros
lista_registros = []

# Contadores
meses_con_error = []
exitos = 0
errores = 0

# Definir fechas importantes
fecha_inicio_real = "1995-06-16"
fecha_hoy = datetime.now().strftime('%Y-%m-%d')

# Establecer el rango de fechas
fecha_inicio = "1995-06-01"
fecha_final = datetime.now().strftime('%Y-%m-%d')

# Generar los puntos de corte a inicio de mes (MS = Month Start)
fechas_inicio_mes = pd.date_range(start = fecha_inicio, end = fecha_final, freq = 'MS')

# Iterar por cada mes
for i, fecha_inicio_mes in enumerate(fechas_inicio_mes):

    # se calcula la fecha de fin de mes
    fecha_fin_mes = (fecha_inicio_mes + pd.offsets.MonthEnd(0))

    # start_date es el primer día del mes, excepto en junio de 1995
    start_date = fecha_inicio_mes.strftime('%Y-%m-%d')
    if fecha_inicio_mes < datetime.strptime(fecha_inicio_real, "%Y-%m-%d"):
        start_date = fecha_inicio_real

    # end_date es el último día del mes, excepto en el mes actual
    end_date = fecha_fin_mes.strftime('%Y-%m-%d')
    if fecha_fin_mes > datetime.now():
        end_date = fecha_hoy

    print(f"Extrayendo datos de {start_date} a {end_date}...")

    # Ejecutar la solicitud
    obs_params = {
        "api_key": api_key,
        "start_date": start_date,
        "end_date": end_date
    }

    try:
        response = requests.get(url, params = obs_params)

        if response.status_code == 200:
            datos_mes = response.json()
            lista_registros.extend(datos_mes)
            exitos += 1
            print(f"...solicitud exitosa")
        else:
            errores += 1
            meses_con_error.append({'periodo': start_date,
                                    'error': response.status_code})
            print(f"Error {response.status_code} en el periodo {start_date}.")
            if response.status_code == 429:
                break

    except Exception as e:
        print(f"Error de conexión: {e}")
        break

    # Pausa para respetar los límites de la API de la NASA
    time.sleep(2)

df_registros = pd.DataFrame(lista_registros)

print(f"Proceso terminado. Registros: {len(df_registros)}; Éxitos: {exitos}; Errores: {errores}")

Para trabajar con una copia del DataFrame previamente descargado df_registros

df_apod = df_registros.copy()

Para guardar el DataFrame previamente descargado df_registros como un CSV

df_registros.to_csv('api_apod_data.csv', index=False, encoding='utf-8-sig', sep=';')

Preguntas de cada miembro del equipo

De acuerdo a la regla de correspondencia, las palabras asignadas a cada integrante del equipo son las siguientes:

  • B - retrograde - (Betancourt Peralta Diego)
  • C - supernova - (Canul Hernández Erick Iván)
  • G - nebula - (Gutiérrez Gutiérrez José Omar)
  • H - planetary - (Hernández Pérez Maximiliano)
  • T - elliptical - (Torres Vargas Brenda Poulette)

Basándose en solicitudes de la API en el campo explanation haz búsquedas basadas en tu palabra y responde la siguientes preguntas:

  1. Para las búsquedas de tu palabra, ¿cuántos resultados obtuviste?
  2. Para las búsquedas de tu palabra, ¿en qué rangos de fechas se introdujo el recurso?
  3. Para las búsquedas de tu palabra, ¿cuáles son los “media_type” más comunes?
  4. Para las búsquedas de tu palabra, ¿quiénes son los autores o instituciones propietaria de los derechos (i.e. el copyright)?

Definimos una función llamada buscar_palabra() que realizara la búsqueda de la palabra palabra en el campo “explanation” del Dataframe dataset. La función devuelve las respuestas a las preguntas solicitadas.

def buscar_palabra(palabra, dataset):

    palabra = palabra.lower()

    # Filtrar el dataset por palabra en el campo "explanation"
    df_palabra = dataset.loc[dataset['explanation'].str.contains(palabra, case=False, na=False)]

    if len(df_palabra) > 0:

        # 1. ¿Cuántos resultados obtuviste?
        total_resultados = len(df_palabra)

        # 2. ¿En qué rangos de fechas se introdujo el recurso?
        fecha_min = df_palabra['date'].min()
        fecha_max = df_palabra['date'].max()

        # 3. ¿Cuáles son los "media_type" más comunes?

        # Frecuencia de cada 'media_type'
        media_type_conteos = df_palabra['media_type'].value_counts()

        # Nombre y valor del 'media_type' más común
        var_media_type = media_type_conteos.index[0]
        conteo_media_type = media_type_conteos.iloc[0]

        # 4. ¿Quiénes son los autores o instituciones propietaria de los derechos (i.e. el copyright)?

        # Diccionario para homologación de acrónimos y nombres con errores
        diccionario_homologacion = {
            "AATB": "Anglo-Australian Telescope Board",
            "NASA": "National Aeronautics and Space Administration",
            "ESA": "European Space Agency",
            "JPL": "Jet Propulsion Laboratory",
            "ESO": "European Southern Observatory",
            "NSF": "National Science Foundation",
            "NOAO": "National Optical Astronomy Observatory",
            "Tunc Tezel": "Tunç Tezel",
            "Tun� Tezel": "Tunç Tezel",
            "Ant�nio Cidad�o": "António Cidadão"
        }

        # Obtener los registros con copyright
        lista_autores = df_palabra['copyright'].dropna()

        # Lista vacía para almacenar los nombres separados y limpios
        lista_autores_limpia = []

        for registro in lista_autores:
            # Eliminar todo lo que venga después de "Explanation:", de ":"
            registro_original = registro.split('Explanation:')[0].split(':')[0]

            # Normalizar separadores (and, &) con comas
            registro_normalizado = registro_original.replace(' and ', ',').replace(' & ', ',')

            # Separar nombres por comas en una lista
            nombres_separados = registro_normalizado.split(",")

            # Quitar saltos de linea \n , eliminar todo lo que venga después de "(TWAN):" y limpiar espacios sobrantes
            nombres_limpios = [nombre.replace('\n',' ').split('(TWAN)')[0].strip() for nombre in nombres_separados if nombre.strip()]

            # Validar y homologar cada nombre
            for nombre in nombres_limpios:
                if nombre:
                    # Homologar usando el diccionario. Si no existe la sigla, conserva el nombre original.
                    nombre_homologado = diccionario_homologacion.get(nombre, nombre)
                    # Agregar el nombre limpio a la lista
                    lista_autores_limpia.append(nombre_homologado)

        # Frecuencia de cada autor/institución
        autores_conteos = pd.Series(lista_autores_limpia).value_counts().head(10)

        # Contar los registros con copyright
        conteo_copyright = df_palabra['copyright'].notna().sum()
        # Contar los registros que son de dominio público (registros vacíos)
        conteo_dominio_publico = df_palabra['copyright'].isna().sum()

        # Impresión de resultados
        print("="*40)
        print(f"Registros totales en el dataset: {len(dataset)}")
        print(f"Desde {dataset['date'].min()} hasta {dataset['date'].max()}")
        print(f"\nPalabra: '{palabra}'")
        print("-"*40)

        print(f"1. Resultados obtenidos: {total_resultados}")

        print(f"\n2. El recurso se introdujo desde {fecha_min} hasta {fecha_max}.")

        print(f"\n3. El 'media_type' más común es '{var_media_type}' con {conteo_media_type} registros.")
        print("\n--- Tabla de Frecuencias ---")
        print(media_type_conteos.to_string(header=False))

        print(f"\n4. Principales autores e instituciones propietarias de los derechos:")
        print("\n--- Tabla de Frecuencias ---")
        print(autores_conteos.to_string(header=False))
        print(f"\nRegistros con Copyright: {conteo_copyright}")
        print(f"Registros de Dominio Público: {conteo_dominio_publico}")
        print("="*40)
    else:
        print(f"\nNo se encontraron resultados para la palabra '{palabra}'.")

Resultados:

  • B - retrograde - (Betancourt Peralta Diego)
buscar_palabra("retrograde", df_apod)
========================================
Registros totales en el dataset: 11288
Desde 1995-06-16 hasta 2026-05-16

Palabra: 'retrograde'
----------------------------------------
1. Resultados obtenidos: 30

2. El recurso se introdujo desde 2001-12-20 hasta 2026-05-06.

3. El 'media_type' más común es 'image' con 29 registros.

--- Tabla de Frecuencias ---
image    29
video     1

4. Principales autores e instituciones propietarias de los derechos:

--- Tabla de Frecuencias ---
Tunç Tezel                        15
Peter Wienerroither                1
John Pane                          1
Western U.                         1
Athabasca U.                       1
Large Binocular Telescope Obs.     1
John Kraus                         1

Registros con Copyright: 19
Registros de Dominio Público: 11
========================================
  • C - supernova - (Canul Hernández Erick Iván)
buscar_palabra("supernova", df_apod)
========================================
Registros totales en el dataset: 11288
Desde 1995-06-16 hasta 2026-05-16

Palabra: 'supernova'
----------------------------------------
1. Resultados obtenidos: 785

2. El recurso se introdujo desde 1995-06-21 hasta 2026-05-14.

3. El 'media_type' más común es 'image' con 768 registros.

--- Tabla de Frecuencias ---
image    768
video     17

4. Principales autores e instituciones propietarias de los derechos:

--- Tabla de Frecuencias ---
Robert Gendler                      16
Martin Pugh                         12
Adam Block                          12
Anglo-Australian Telescope Board    11
Don Goldman                          8
Carlos Taylor                        5
Astro Anarchy                        4
Star Shadows Remote Observatory      4
StarryScapes                         4
European Southern Observatory        4

Registros con Copyright: 344
Registros de Dominio Público: 441
========================================
  • G - nebula - (Gutiérrez Gutiérrez José Omar)
buscar_palabra("nebula", df_apod)
========================================
Registros totales en el dataset: 11288
Desde 1995-06-16 hasta 2026-05-16

Palabra: 'nebula'
----------------------------------------
1. Resultados obtenidos: 2550

2. El recurso se introdujo desde 1995-06-24 hasta 2026-05-15.

3. El 'media_type' más común es 'image' con 2530 registros.

--- Tabla de Frecuencias ---
image    2530
video      19
other       1

4. Principales autores e instituciones propietarias de los derechos:

--- Tabla de Frecuencias ---
Robert Gendler                      47
Anglo-Australian Telescope Board    45
Martin Pugh                         41
Adam Block                          39
Don Goldman                         26
Rogelio Bernal Andreo               23
Jean-Charles Cuillandre             17
Ken Crawford                        15
UKS Telescope                       15
Tony Hallas                         14

Registros con Copyright: 1682
Registros de Dominio Público: 868
========================================
  • H - planetary - (Hernández Pérez Maximiliano)
buscar_palabra("planetary", df_apod)
========================================
Registros totales en el dataset: 11288
Desde 1995-06-16 hasta 2026-05-16

Palabra: 'planetary'
----------------------------------------
1. Resultados obtenidos: 743

2. El recurso se introdujo desde 1995-06-26 hasta 2026-04-22.

3. El 'media_type' más común es 'image' con 728 registros.

--- Tabla de Frecuencias ---
image    728
video     14
other      1

4. Principales autores e instituciones propietarias de los derechos:

--- Tabla de Frecuencias ---
Don Goldman                         10
Martin Pugh                          6
Robert Gendler                       5
Lynette Cook                         5
Anglo-Australian Telescope Board     5
Adam Block                           4
Chris Hetlage                        3
Nordic Optical Telescope             3
R. Corradi (Isaac Newton Group)      3
Keith Quattrocchi                    3

Registros con Copyright: 247
Registros de Dominio Público: 496
========================================
  • T - elliptical - (Torres Vargas Brenda Poulette)
buscar_palabra("elliptical", df_apod)
========================================
Registros totales en el dataset: 11288
Desde 1995-06-16 hasta 2026-05-16

Palabra: 'elliptical'
----------------------------------------
1. Resultados obtenidos: 336

2. El recurso se introdujo desde 1995-07-28 hasta 2026-04-24.

3. El 'media_type' más común es 'image' con 327 registros.

--- Tabla de Frecuencias ---
image    327
video      9

4. Principales autores e instituciones propietarias de los derechos:

--- Tabla de Frecuencias ---
Jean-Charles Cuillandre                   5
Stephen Leshin                            5
Anthony Ayiomamitis                       4
António Cidadão                           4
Adam Block                                4
Marco Lorenzi                             4
Catalin Paduraru                          3
Robert Gendler                            3
National Science Foundation               3
National Optical Astronomy Observatory    3

Registros con Copyright: 169
Registros de Dominio Público: 167
========================================