Объединение Pointdraw и Sample в Holoviews - PullRequest
0 голосов
/ 12 ноября 2018

Я пытаюсь объединить функциональность Holoviews Pointdraw с ее функциональностью примера (я не смог найти конкретную страницу, но она показана в действии здесь http://holoviews.org/gallery/demos/bokeh/mandelbrot_section.html)

В частности, я хочу иметь два сюжета с интерактивностью. Один слева показывает цветовую карту, а другой справа показывает образец (отрезок строки) цветовой карты. Это достигается с помощью .sample. Внутри этого правильного графика я хотел бы иметь точки, которые можно рисовать, перемещать и удалять, как правило, с помощью pointdraw. Затем я также хотел бы получить доступ к их координатам после завершения перемещения, что возможно, если следовать примеру из документации.

Теперь у меня есть два работающих независимо, следуя приведенным выше примерам. Но в сочетании с тем способом, который у меня есть, это приводит к сюжету, который выглядит следующим образом: enter image description here В нем есть элементы, которые я ищу, за исключением точек, с которыми невозможно взаимодействовать. Это как-то связано с потоками Holoviews, но я не уверен, как это решить. Кто-нибудь сможет помочь?

Код, который генерирует выше:

%%opts Points (color='color' size=10) [tools=['hover'] width=400 height=400] 
%%opts Layout [shared_datasource=True] Table (editable=True)

import param
import numpy as np
import holoviews as hv
hv.extension('bokeh', 'matplotlib')
from holoviews import streams

def lorentzian(x, x0, gamma):
    return 1/np.pi*1/2*gamma/((x-x0)**2+(1/2*gamma)**2)

xs = np.arange(0,4*np.pi,0.05)
ys = np.arange(0,4*np.pi,0.05)
data = hv.OrderedDict({'x': [2., 2., 2.], 'y': [0.5, 0.4, 0.2], 'color': ['red', 'green', 'blue']})

z = lorentzian(xs.reshape(len(xs),1),2*np.sin(ys.reshape(1,len(ys)))+5,1) + lorentzian(xs.reshape(len(xs),1),-2*np.sin(ys.reshape(1,len(ys)))+5,1)

def dispersions(f0):
    points = hv.Points(data, vdims=['color']).redim.range(x=(xs[0], xs[-1]), y=(np.min(z), np.max(z)))
    point_stream = streams.PointDraw(data=points.columns(), source=points, empty_value='black')
    image = hv.Image(z, bounds=(xs[0], ys[0], xs[-1], ys[-1]))
    return image* hv.VLine(x=f0) + image.sample(x=f0)*points

dmap = hv.DynamicMap(dispersions, kdims=['f0'])
dmap.redim.range(f0=(0,10)).redim.step(f0=(0.1))

Я прошу прощения за странную функцию, которую мы строим, я не мог сразу придумать простую.

1 Ответ

0 голосов
/ 12 ноября 2018

Исходя из вашего примера, мне еще не совсем ясно, что вы будете делать с точками, но у меня есть некоторые предложения по улучшению структуры кода.

В общем, всегда лучше составлять графики изнесколько отдельных DynamicMaps, чем создание единой DynamicMap, которая делает все.Он не только более удобен для компоновки, но также получает дескрипторы для отдельных объектов, позволяющие настраивать потоки для прослушивания изменений в каждом компоненте, и, что более важно, он более эффективен, будут обновляться только те графики, которые необходимо обновить.В вашем примере я бы разделил код следующим образом:

def lorentzian(x, x0, gamma):
    return 1/np.pi*1/2*gamma/((x-x0)**2+(1/2*gamma)**2)

xs = np.arange(0,4*np.pi,0.05)
ys = np.arange(0,4*np.pi,0.05)
data = hv.OrderedDict({'x': [2., 2., 2.], 'y': [0.5, 0.4, 0.2], 'color': ['red', 'green', 'blue']})

points = hv.Points(data, vdims=['color']).redim.range(x=(xs[0], xs[-1]), y=(np.min(z), np.max(z)))
image = hv.Image(z, bounds=(xs[0], ys[0], xs[-1], ys[-1]))

z = lorentzian(xs.reshape(len(xs),1),2*np.sin(ys.reshape(1,len(ys)))+5,1) + lorentzian(xs.reshape(len(xs),1),-2*np.sin(ys.reshape(1,len(ys)))+5,1)
taps = []

def vline(f0):
    return hv.VLine(x=f0)

def sample(f0):
    return image.sample(x=f0)

dim = hv.Dimension('f0', step=0.1, range=(0,10))
vline_dmap = hv.DynamicMap(vline, kdims=[dim])
sample_dmap = hv.DynamicMap(sample, kdims=[dim])
point_stream = streams.PointDraw(data=points.columns(), source=points, empty_value='black')

(image * vline_dmap + sample_dmap * points)

Поскольку изображение и точки сами по себе не являются динамическими, нет смысла помещать их в DynamicMap, а VLine и сэмплированная кривая легкоотщеплять.Поток PointDraw еще ничего не делает, но теперь вы можете настроить его как еще одну DynamicMap, которую вы можете составить с остальными.

...