Аннотирующий интерактивный сюжет с изображениями по щелчку мыши в python - PullRequest
0 голосов
/ 30 апреля 2018

Я пытался найти способ отобразить изображение на графике питона с изображением, соответствующим положению щелчка мыши. Вот где я до: Аннотированный сюжет (требуется изображение вместо текста)

Я могу получить код для отображения значения на цветной панели, в зависимости от того, на каком полигоне я щелкаю (они построены из обычного plt.scatter, поэтому все, что работает с точками рассеяния, будет работать с этим). У каждого многоугольника есть соответствующее изображение, которое я хотел бы отобразить вместо значения цвета.

Кто-нибудь знает, как это сделать?

В настоящее время я использую mpldatacursor для отображения аннотации, но если другой пакет будет лучше, пожалуйста, дайте мне знать!

С наилучшими пожеланиями и большое спасибо,

Tom

Вот код (большая часть которого не является необходимой для этого, поскольку включает в себя построение полигонов). Извиняюсь за плохой код, я новичок

import numpy as np
import matplotlib.pyplot as plt
import mpldatacursor
import matplotlib.image as mpimg
import sys
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import Voronoi, voronoi_plot_2d
import pandas as pd
import matplotlib.cm as cm
import matplotlib as mpl
import seaborn as sns


def voronoi_finite_polygons_2d(vor, radius=None):
    """
    Reconstruct infinite voronoi regions in a 2D diagram to finite
    regions.
    Parameters
    ----------
    vor : Voronoi
        Input diagram
    radius : float, optional
        Distance to 'points at infinity'.
    Returns
    -------
    regions : list of tuples
        Indices of vertices in each revised Voronoi regions.
    vertices : list of tuples
        Coordinates for revised Voronoi vertices. Same as coordinates
        of input vertices, with 'points at infinity' appended to the
        end.
    """

    if vor.points.shape[1] != 2:
        raise ValueError("Requires 2D input")

    new_regions = []
    new_vertices = vor.vertices.tolist()

    center = vor.points.mean(axis=0)
    if radius is None:
        radius = vor.points.ptp().max()*2

    # Construct a map containing all ridges for a given point
    all_ridges = {}
    for (p1, p2), (v1, v2) in zip(vor.ridge_points, vor.ridge_vertices):
        all_ridges.setdefault(p1, []).append((p2, v1, v2))
        all_ridges.setdefault(p2, []).append((p1, v1, v2))

    # Reconstruct infinite regions
    for p1, region in enumerate(vor.point_region):
        vertices = vor.regions[region]

        if all(v >= 0 for v in vertices):
            # finite region
            new_regions.append(vertices)
            continue

        # reconstruct a non-finite region
        ridges = all_ridges[p1]
        new_region = [v for v in vertices if v >= 0]

        for p2, v1, v2 in ridges:
            if v2 < 0:
                v1, v2 = v2, v1
            if v1 >= 0:
                # finite ridge: already in the region
                continue

            # Compute the missing endpoint of an infinite ridge

            t = vor.points[p2] - vor.points[p1] # tangent
            t /= np.linalg.norm(t)
            n = np.array([-t[1], t[0]])  # normal

            midpoint = vor.points[[p1, p2]].mean(axis=0)
            direction = np.sign(np.dot(midpoint - center, n)) * n
            far_point = vor.vertices[v2] + direction * radius

            new_region.append(len(new_vertices))
            new_vertices.append(far_point.tolist())

        # sort region counterclockwise
        vs = np.asarray([new_vertices[v] for v in new_region])
        c = vs.mean(axis=0)
        angles = np.arctan2(vs[:,1] - c[1], vs[:,0] - c[0])
        new_region = np.array(new_region)[np.argsort(angles)]

        # finish
        new_regions.append(new_region.tolist())

    return new_regions, np.asarray(new_vertices)



parameters = ['Age (Gyr)']#, 'Weighted metalicity M/H', 'Mass to light ratio', 'Total mass below -0.5 M/H', 'Fractional mass below -0.5 M/H']

all_info = [[0 for i in range(970)] for j in range(7)] # inititlise final array

all_info[0][:] = np.loadtxt('temp_matched.csv', usecols=(0),skiprows=0, delimiter=',')
all_info[1][:] = np.loadtxt('temp_matched.csv', usecols=(1),skiprows=0, delimiter=',')
all_info[2][:] = np.loadtxt('temp_matched.csv', usecols=(2),skiprows=0, delimiter=',')
all_info[3][:] = np.loadtxt('temp_matched.csv', usecols=(3),skiprows=0, delimiter=',')
all_info[4][:] = np.loadtxt('temp_matched.csv', usecols=(4),skiprows=0, delimiter=',')

mass_frac = np.loadtxt('weight_info.csv',skiprows=0)

contour_mass = np.loadtxt('tb.csv', usecols=(23),skiprows=1, delimiter=',')
contour_rad = np.loadtxt('tb.csv', usecols=(11),skiprows=1, delimiter=',')
z = np.loadtxt('tb.csv', usecols=(24),skiprows=1, delimiter=',')

#convert to kpc
contour_rad = contour_rad / 3600.0 #degrees
contour_rad = (contour_rad / 180.0) * 3.14159 #degrees to rads
q_0 = (0.3089 / 2) - 0.6911 #q_0 from q_0 = (\Omega_M / 2) - \Omega_Lambda
distance = ((2.99E8 * z) / 67740.0) * (1 + (z*(1-q_0))/(np.sqrt(1+(2*q_0) * z) + 1 + q_0 * z))
distance = distance * 1000.0 #distance (into kpc)
contour_rad = distance * np.tan(contour_rad) #radius from radians
contour_rad = np.log10(contour_rad) #to log (if needed for plotting point density)


true_mass = [0] * len(all_info[0][:])

for h in range(len(all_info[0][:])):
    true_mass[h] = 10 ** all_info[0][h]
tot_frac_mass = true_mass * mass_frac
all_info[5][:] = tot_frac_mass[:]

all_info[6][:] = mass_frac # fractional mass



#do the actual voronoi stuff

allpoints = [all_info[0][:], all_info[1][:]]
points = np.swapaxes(allpoints,0,1)
vor = Voronoi(points) # voronoi calc
regions, vertices = voronoi_finite_polygons_2d(vor)


for item in range(len(parameters)):

    plt.figure(item+1)
    voronoi_plot_2d(vor, show_vertices = False, show_points = False, line_alpha = 0.5)
    colour = all_info[item + 2][:]
    minima = min(colour)
    maxima = max(colour)

    norm = mpl.colors.Normalize(vmin=minima, vmax=maxima, clip=True)
    mapper = cm.ScalarMappable(norm=norm, cmap=cm.plasma)

    img=mpimg.imread('/home/tom/Documents/phd/diagonals/re8/added_spectra/plots/mass_frac/mass_fraction9.png')


    count = 0
    for region in regions:
        polygon = vertices[region]
        if ((colour[count] < maxima) & (colour[count] > minima)):
            plt.fill(*zip(*polygon), color=mapper.to_rgba(colour[count]), zorder=1, label=colour[count])
        count = count + 1


    # plot

    #for r in range(len(vor.point_region)):
    #   region = vor.regions[vor.point_region[r]]
    #   if not -1 in region:
    #       polygon = [vor.vertices[i] for i in region]
    #       plt.fill(*zip(*polygon), color=mapper.to_rgba(colour[r]), zorder=1)


    #im = plt.scatter(all_info[0][:], all_info[1][:], c=all_info[item + 2][:], cmap=cm.plasma, alpha=1.0)

    #use this line instead to limit colour according to vmin and vmax
    im = plt.scatter(all_info[0][:], all_info[1][:], c=all_info[item + 2][:], cmap=cm.plasma, alpha=1.0, vmin=minima, vmax=maxima)

    cb = plt.colorbar(im)
    plt.ylabel('Radius log$_{10}$(Kpc)')
    plt.xlabel('Mass: log$_{10}$(M$_{\odot}$)')
    cb.set_label(label='%s' %(parameters[item]))
    plt.title('Mass size: %s' %(parameters[item]))
    plt.xlim(8.5, 11.5)
    plt.ylim(-0.2, 1.2)


    mpldatacursor.datacursor(formatter='{label}'.format)
    #mpldatacursor.datacursor(formatter='{label}'.format)


plt.show()  
...