Лассо выберите точки из графика matplotlib: цвета меняются при выборе - PullRequest
0 голосов
/ 07 мая 2020

Я пытаюсь выбрать точки с помощью инструмента лассо из диаграммы рассеяния matplotlib. Здесь показана демонстрация:

https://matplotlib.org/3.1.0/gallery/widgets/lasso_selector_demo_sgskip.html

В этом примере все точки разброса имеют одинаковый цвет. У меня есть диаграмма рассеяния разного цвета, хотя это не должно иметь значения. Вот мой код:

xvals = [pt[0] for pt in list(positions.values())]
yvals = [pt[1] for pt in list(positions.values())]

nr_colors=10

subplot_kw = dict(xlim=(min(xvals), max(xvals)), ylim=(min(yvals), max(yvals)), autoscale_on=False)
fig,ax = plt.subplots(subplot_kw=subplot_kw)
pts = ax.scatter(x=xvals,y=yvals,c=coloring,s=sizing/15000,cmap=plt.cm.get_cmap("RdYlGn"))

selector = lassoselector.SelectFromCollection(ax, pts)

def accept(event):
    if event.key == "enter":        
        selector.pointslist.append(selector.ind)
        print("Appended a cluster!")
    elif event.key == "1":
        selector.disconnect()
        ax.set_title("")
        fig.canvas.draw()
        plt.close()
        print("Analyzing clusters...")
        vals=[]
        for selected_rows in selector.pointslist:
            vals.append(np.mean(whereUsed.T.values[selected_rows],axis=0))

        diff = vals[0]-vals[1]
        df = pd.DataFrame({"Difference":diff})
        df.index = dimension_value_names
        df.sort_values(by="Difference",ascending=True).plot(kind="barh",legend=False,title="Cluster 1 - Cluster 2",figsize=(10,15))




fig.canvas.mpl_connect("key_press_event", accept)
ax.set_title("Press enter to accept selected points, press 1 to close")

plt.show()

Как видите, код очень похож на пример. Единственная разница в том, что мой объект pts содержит много цветов вместо одного. Итак, при доступе к цветам в классе через:

    self.fc = collection.get_facecolors()  

я должен получить свой список цветов. По какой-то причине это не работает, и когда я начинаю рисовать, self.f c содержит только один цвет (синий). Превращение всего изображения в синий и более светлый оттенок синего, как в примере. Как сохранить исходные цвета и просто убрать выделение, которое я не использую?

1 Ответ

0 голосов
/ 18 июля 2020

Я думаю, что это ошибка.

Если вы запустите его в интерактивном режиме, он не изменит цвет лица на синий. В смысле сначала создать фигуру с разбросом, а затем инициализировать селектор. Кажется, что цвета лица из коллекции не заполняются до тех пор, пока фигура не будет нарисована, если селектор вызывается до того, как фигура будет нарисована, тогда метод get_facecolors () вернет цвет по умолчанию (синий).

Я сделал обходной путь, который может быть некрасивым, но он помогает. В основном я включил необязательный параметр в класс SelectFromCollection, так что вместо получения цветов лица из коллекции он использовал этот параметр. Я включил весь код ниже для справки. Основное изменение класса - это строка: if facecolors is not None: self.f c = facecolors

'' '

import numpy as np

from matplotlib.widgets import LassoSelector
from matplotlib.path import Path


class SelectFromCollection(object):
    # Select indices from a matplotlib collection using `LassoSelector`.
    #
    # Selected indices are saved in the `ind` attribute. This tool fades out the
    # points that are not part of the selection (i.e., reduces their alpha
    # values). If your collection has alpha < 1, this tool will permanently
    # alter the alpha values.
    #
    # Note that this tool selects collection objects based on their *origins*
    # (i.e., `offsets`).
    #
    # Parameters
    # ----------
    # ax : :class:`~matplotlib.axes.Axes`
    #     Axes to interact with.
    #
    # collection : :class:`matplotlib.collections.Collection` subclass
    #     Collection you want to select from.
    #
    # alpha_other : 0 <= float <= 1
    #     To highlight a selection, this tool sets all selected points to an
    #     alpha value of 1 and non-selected points to `alpha_other`.
    #

    def __init__(self, ax, collection, alpha_other=0.3, facecolors=None):
        self.canvas = ax.figure.canvas
        self.collection = collection
        self.alpha_other = alpha_other

        self.xys = collection.get_offsets()
        self.Npts = len(self.xys)

        # Ensure that we have separate colors for each object
        self.fc = collection.get_facecolors()
        if len(self.fc) == 0:
            raise ValueError('Collection must have a facecolor')
        elif len(self.fc) == 1:
            self.fc = np.tile(self.fc, (self.Npts, 1))

        if facecolors is not None: self.fc = facecolors

        self.lasso = LassoSelector(ax, onselect=self.onselect)
        self.ind = []

    def onselect(self, verts):
        path = Path(verts)
        self.ind = np.nonzero(path.contains_points(self.xys))[0]
        self.fc[:, -1] = self.alpha_other
        self.fc[self.ind, -1] = 1
        self.collection.set_facecolors(self.fc)
        self.canvas.draw_idle()

    def disconnect(self):
        self.lasso.disconnect_events()
        self.fc[:, -1] = 1
        self.collection.set_facecolors(self.fc)
        self.canvas.draw_idle()


if __name__ == '__main__':
    import matplotlib.pyplot as plt

    # Fixing random state for reproducibility
    np.random.seed(19680801)

    data = np.random.rand(100, 100)
    x_2d = np.zeros((100,100))
    y_2d = np.zeros((100,100))
    for r_ in range(100):
        x_2d[r_,:] = np.arange(100)
        y_2d[:,r_] = np.arange(100)

    fig, ax = plt.subplots()
    pts = ax.scatter(x_2d.flatten(), y_2d.flatten(), c=data.flatten(), cmap=plt.cm.jet)
    facecolors = plt.cm.jet(data.flatten())
    selector = SelectFromCollection(ax, pts, facecolors=facecolors)

    def accept(event):
        if event.key == "enter":
            print("Selected points:")
            print(selector.xys[selector.ind])
            selector.disconnect()
            ax.set_title("")
            fig.canvas.draw()

    fig.canvas.mpl_connect("key_press_event", accept)
    ax.set_title("Press enter to accept selected points.")

    plt.show()

' ''

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...