origen y extensión en #imshow

imshow()le permite renderizar una imagen (ya sea una matriz 2D que se mapeará en color (basada en norm y cmap ) o una matriz 3D RGB(A) que se usará tal cual) en una región rectangular en el espacio de datos. La orientación de la imagen en el renderizado final está controlada por los argumentos de palabra clave de origen y extensiónAxesImage (y los atributos en la instancia resultante) y los límites de datos de los ejes.

Los argumentos de palabra clave de extensión controlan el cuadro delimitador en las coordenadas de datos que la imagen llenará especificada como en las coordenadas de datos , el argumento de palabra clave de origen controla cómo la imagen llena ese cuadro delimitador, y la orientación en la imagen renderizada final también se ve afectada por los límites de los ejes .(left, right, bottom, top)

Insinuación

La mayor parte del código a continuación se usa para agregar etiquetas y texto informativo a los gráficos. Los efectos descritos de origen y extensión se pueden ver en los gráficos sin necesidad de seguir todos los detalles del código.

Para una comprensión rápida, puede omitir los detalles del código a continuación y continuar directamente con la discusión de los resultados.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec


def index_to_coordinate(index, extent, origin):
    """Return the pixel center of an index."""
    left, right, bottom, top = extent

    hshift = 0.5 * np.sign(right - left)
    left, right = left + hshift, right - hshift
    vshift = 0.5 * np.sign(top - bottom)
    bottom, top = bottom + vshift, top - vshift

    if origin == 'upper':
        bottom, top = top, bottom

    return {
        "[0, 0]": (left, bottom),
        "[M', 0]": (left, top),
        "[0, N']": (right, bottom),
        "[M', N']": (right, top),
    }[index]


def get_index_label_pos(index, extent, origin, inverted_xindex):
    """
    Return the desired position and horizontal alignment of an index label.
    """
    if extent is None:
        extent = lookup_extent(origin)
    left, right, bottom, top = extent
    x, y = index_to_coordinate(index, extent, origin)

    is_x0 = index[-2:] == "0]"
    halign = 'left' if is_x0 ^ inverted_xindex else 'right'
    hshift = 0.5 * np.sign(left - right)
    x += hshift * (1 if is_x0 else -1)
    return x, y, halign


def get_color(index, data, cmap):
    """Return the data color of an index."""
    val = {
        "[0, 0]": data[0, 0],
        "[0, N']": data[0, -1],
        "[M', 0]": data[-1, 0],
        "[M', N']": data[-1, -1],
    }[index]
    return cmap(val / data.max())


def lookup_extent(origin):
    """Return extent for label positioning when not given explicitly."""
    if origin == 'lower':
        return (-0.5, 6.5, -0.5, 5.5)
    else:
        return (-0.5, 6.5, 5.5, -0.5)


def set_extent_None_text(ax):
    ax.text(3, 2.5, 'equals\nextent=None', size='large',
            ha='center', va='center', color='w')


def plot_imshow_with_labels(ax, data, extent, origin, xlim, ylim):
    """Actually run ``imshow()`` and add extent and index labels."""
    im = ax.imshow(data, origin=origin, extent=extent)

    # extent labels (left, right, bottom, top)
    left, right, bottom, top = im.get_extent()
    if xlim is None or top > bottom:
        upper_string, lower_string = 'top', 'bottom'
    else:
        upper_string, lower_string = 'bottom', 'top'
    if ylim is None or left < right:
        port_string, starboard_string = 'left', 'right'
        inverted_xindex = False
    else:
        port_string, starboard_string = 'right', 'left'
        inverted_xindex = True
    bbox_kwargs = {'fc': 'w', 'alpha': .75, 'boxstyle': "round4"}
    ann_kwargs = {'xycoords': 'axes fraction',
                  'textcoords': 'offset points',
                  'bbox': bbox_kwargs}
    ax.annotate(upper_string, xy=(.5, 1), xytext=(0, -1),
                ha='center', va='top', **ann_kwargs)
    ax.annotate(lower_string, xy=(.5, 0), xytext=(0, 1),
                ha='center', va='bottom', **ann_kwargs)
    ax.annotate(port_string, xy=(0, .5), xytext=(1, 0),
                ha='left', va='center', rotation=90,
                **ann_kwargs)
    ax.annotate(starboard_string, xy=(1, .5), xytext=(-1, 0),
                ha='right', va='center', rotation=-90,
                **ann_kwargs)
    ax.set_title('origin: {origin}'.format(origin=origin))

    # index labels
    for index in ["[0, 0]", "[0, N']", "[M', 0]", "[M', N']"]:
        tx, ty, halign = get_index_label_pos(index, extent, origin,
                                             inverted_xindex)
        facecolor = get_color(index, data, im.get_cmap())
        ax.text(tx, ty, index, color='white', ha=halign, va='center',
                bbox={'boxstyle': 'square', 'facecolor': facecolor})
    if xlim:
        ax.set_xlim(*xlim)
    if ylim:
        ax.set_ylim(*ylim)


def generate_imshow_demo_grid(extents, xlim=None, ylim=None):
    N = len(extents)
    fig = plt.figure(tight_layout=True)
    fig.set_size_inches(6, N * (11.25) / 5)
    gs = GridSpec(N, 5, figure=fig)

    columns = {'label': [fig.add_subplot(gs[j, 0]) for j in range(N)],
               'upper': [fig.add_subplot(gs[j, 1:3]) for j in range(N)],
               'lower': [fig.add_subplot(gs[j, 3:5]) for j in range(N)]}
    x, y = np.ogrid[0:6, 0:7]
    data = x + y

    for origin in ['upper', 'lower']:
        for ax, extent in zip(columns[origin], extents):
            plot_imshow_with_labels(ax, data, extent, origin, xlim, ylim)

    columns['label'][0].set_title('extent=')
    for ax, extent in zip(columns['label'], extents):
        if extent is None:
            text = 'None'
        else:
            left, right, bottom, top = extent
            text = (f'left: {left:0.1f}\nright: {right:0.1f}\n'
                    f'bottom: {bottom:0.1f}\ntop: {top:0.1f}\n')
        ax.text(1., .5, text, transform=ax.transAxes, ha='right', va='center')
        ax.axis('off')
    return columns

Extensión predeterminada #

Primero, echemos un vistazo al valor predeterminado.extent=None

generate_imshow_demo_grid(extents=[None])
extensión=, origen: superior, origen: inferior
{'label': [<AxesSubplot: title={'center': 'extent='}>], 'upper': [<AxesSubplot: title={'center': 'origin: upper'}>], 'lower': [<AxesSubplot: title={'center': 'origin: lower'}>]}

Generalmente, para una matriz de forma (M, N), el primer índice corre a lo largo de la vertical, el segundo índice corre a lo largo de la horizontal. Los centros de píxeles están en posiciones enteras que van de 0 a horizontal y de 0 a vertical. El origen determina cómo se rellenan los datos en el cuadro delimitador.N' = N - 1M' = M - 1

para origin='lower':

  • [0, 0] está en (izquierda, abajo)

  • [M', 0] está en (izquierda, arriba)

  • [0, N'] está en (derecha, abajo)

  • [M', N'] está en (derecha, arriba)

origin='upper'invierte la dirección de los ejes verticales y el relleno:

  • [0, 0] está en (izquierda, arriba)

  • [M', 0] está en (izquierda, abajo)

  • [0, N'] está en (derecha, arriba)

  • [M', N'] está en (derecha, abajo)

En resumen, la posición del índice [0, 0] así como la extensión están influenciadas por el origen :

origen

[0, 0] posición

medida

superior

arriba a la izquierda

(-0.5, numcols-0.5, numrows-0.5, -0.5)

más bajo

abajo a la izquierda

(-0.5, numcols-0.5, -0.5, numrows-0.5)

El valor predeterminado de origen está establecido por rcParams["image.origin"](predeterminado: 'upper'), que de manera predeterminada 'upper'coincide con las convenciones de indexación de matrices en las convenciones de indexación de imágenes gráficas y matemáticas.

Extensión explícita #

Al establecer la extensión , definimos las coordenadas del área de la imagen. Los datos de la imagen subyacente se interpolan/se vuelven a muestrear para llenar esa área.

Si los ejes están configurados en escala automática, los límites de vista de los ejes se configuran para que coincidan con la extensión , lo que garantiza que la coordenada establecida por esté en la parte inferior izquierda de los ejes. Sin embargo, esto puede invertir el eje para que no aumenten en la dirección 'natural'.(left, bottom)

extents = [(-0.5, 6.5, -0.5, 5.5),
           (-0.5, 6.5, 5.5, -0.5),
           (6.5, -0.5, -0.5, 5.5),
           (6.5, -0.5, 5.5, -0.5)]

columns = generate_imshow_demo_grid(extents)
set_extent_None_text(columns['upper'][1])
set_extent_None_text(columns['lower'][0])
extensión=, origen: superior, origen: superior, origen: superior, origen: superior, origen: inferior, origen: inferior, origen: inferior, origen: inferior

Extensión explícita y límites de ejes #

Si fijamos los límites de los ejes configurando explícitamente set_xlim/ set_ylim, forzamos un cierto tamaño y orientación de los ejes. Esto puede desacoplar el sentido de 'izquierda-derecha' y 'arriba-abajo' de la imagen de la orientación en la pantalla.

En el siguiente ejemplo, hemos elegido los límites ligeramente más grandes que la extensión (observe las áreas blancas dentro de los ejes).

Si bien mantenemos las extensiones como en los ejemplos anteriores, la coordenada (0, 0) ahora se coloca explícitamente en la parte inferior izquierda y los valores aumentan hacia arriba y hacia la derecha (desde el punto de vista del espectador). Podemos ver eso:

  • La coordenada ancla la imagen que luego llena el cuadro yendo hacia el punto en el espacio de datos.(left, bottom)(right, top)

  • La primera columna es siempre la más cercana a la 'izquierda'.

  • origen controla si la primera fila está más cerca de 'superior' o 'inferior'.

  • La imagen se puede invertir en cualquier dirección.

  • El sentido de 'izquierda-derecha' y 'arriba-abajo' de la imagen puede estar desacoplado de la orientación en la pantalla.

generate_imshow_demo_grid(extents=[None] + extents,
                          xlim=(-2, 8), ylim=(-1, 6))

plt.show()
extensión=, origen: superior, origen: superior, origen: superior, origen: superior, origen: superior, origen: inferior, origen: inferior, origen: inferior, origen: inferior, origen: inferior

Tiempo total de ejecución del script: (0 minutos 4.816 segundos)

Galería generada por Sphinx-Gallery