使用 XArray 数据集再现 Holoviews 示例 box_draw_roi_editor
Reproducing Holoviews example box_draw_roi_editor with XArray Dataset
我正在使用以下 xarray.Dataset
尝试从 holoviews 网站 (https://holoviews.org/gallery/demos/bokeh/box_draw_roi_editor.html#demos-bokeh-gallery-box-draw-roi-editor) 复制以下示例:
holoviews 1.13.2
numpy 1.16.4
xarray 0.14.1
<xarray.Dataset>
Dimensions: (time: 1589, x: 50, y: 50)
Coordinates:
* x (x) float64 4.067e+05 4.067e+05 4.068e+05 ... 4.081e+05 4.082e+05
* y (y) float64 -1.309e+06 -1.309e+06 ... -1.311e+06 -1.311e+06
* time (time) datetime64[ns] 1988-01-04T00:33:06.940187 ... 2019-08-22T00:45:24.121949944
Data variables:
evi (time, y, x) float32 ...
polys = hv.Polygons([])
box_stream = streams.BoxEdit(source=polys)
def roi_curves(data):
if not data or not any(len(d) for d in data.values()):
return hv.NdOverlay({0: hv.Curve([], 'time', 'evi')})
curves = {}
data = zip(data['x0'], data['x1'], data['y0'], data['y1'])
for i, (x0, x1, y0, y1) in enumerate(data):
selection = hv_ds.select(x=(x0, x1), y=(y0, y1))
curves[i] = hv.Curve(selection.aggregate('time', np.mean))
return hv.NdOverlay(curves)
hlines = hv.HoloMap({i: hv.VLine(i) for i in range(2000)}, 'time')
dmap = hv.DynamicMap(roi_curves, streams=[box_stream])
(im * polys + dmap ).opts(
opts.Curve(width=400, framewise=True),
opts.Polygons(fill_alpha=0.2, line_color='white'),
opts.VLine(color='black'))
当我使用 (im * polys + dmap * hlines)
而不是 (im * polys + dmap)
时出现问题
使用 (im * polys + dmap)
的结果接近网站的结果,但缺少代表 time
维度的垂直黑线。
当我使用 (im * polys + dmap * hlines)
时,如 holoviews 示例所示,我得到:TypeError: invalid type promotion
,并且控制台打印以下内容:
...
~\Anaconda3\lib\site-packages\panel\pane\holoviews.py in widgets_from_dimensions(cls, object, widget_types, widgets_type)
395 if vals:
396 if all(isnumeric(v) or isinstance(v, datetime_types) for v in vals) and len(vals) > 1:
--> 397 vals = sorted(vals)
398 labels = [unicode(dim.pprint_value(v)) for v in vals]
399 options = OrderedDict(zip(labels, vals))
TypeError: invalid type promotion
:Layout
.DynamicMap.I :DynamicMap [time]
.DynamicMap.II :DynamicMap [time]
我认为问题出在 hlines
的定义中,因此 我已经尝试 更改 range(2000)
许多其他值,包括长度im
和 hv_ds
中的 time
维度,但错误非常神秘,我不知道如何调试它。
问题: 如何绘制代表 time
维度的垂直线,如 Holoviews 示例中所示?
正如您正确地发现这里的问题是 VLine HoloMap 的整数值。获取正确值的最简单方法是在图像堆栈上使用 .apply
方法,它构建了一个管道并允许您从图像中获取当前时间值。还需要进行一些其他修改才能使其与日期时间一起使用,例如我们必须声明一个空数据集,以便它使用正确的数据类型进行初始化。这是我的尝试:
import numpy as np
import pandas as pd
import xarray as xr
from holoviews import opts
# Create fake dataset
coords={'x': np.arange(50), 'y': np.arange(50),
'time': np.array([1514764800000000000+86400000000000*i for i in range(1589)]).astype('datetime64[ns]')}
evi = xr.DataArray(np.random.rand(50, 50, 1589), coords=coords, dims=['x', 'y', 'time'], name='evi')
hv_ds = hv.Dataset(evi)
# Create stack of images grouped by time
im = hv_ds.to(hv.Image, ['x', 'y'], dynamic=True)
polys = hv.Polygons([])
box_stream = hv.streams.BoxEdit(source=polys)
# Declare an empty DataFrame to declare the types
empty = pd.DataFrame({'time': np.array([], dtype='datetime64[ns]'), 'evi': []})
def roi_curves(data):
if not data or not any(len(d) for d in data.values()):
return hv.NdOverlay({0: hv.Curve(empty, 'time', 'evi')})
curves = {}
data = zip(data['x0'], data['x1'], data['y0'], data['y1'])
for i, (x0, x1, y0, y1) in enumerate(data):
selection = hv_ds.select(x=(x0, x1), y=(y0, y1))
curves[i] = hv.Curve(selection.aggregate('time', np.mean))
return hv.NdOverlay(curves)
# Generate VLines by getting time value from the image frames
def vline(frame):
return hv.VLine(frame.data.time.values)
vlines = im.apply(vline)
dmap = hv.DynamicMap(roi_curves, streams=[box_stream])
(im * polys + dmap * vlines ).opts(
opts.Curve(width=400, framewise=True),
opts.Polygons(fill_alpha=0.2, line_color='white'),
opts.VLine(color='black'))
我正在使用以下 xarray.Dataset
尝试从 holoviews 网站 (https://holoviews.org/gallery/demos/bokeh/box_draw_roi_editor.html#demos-bokeh-gallery-box-draw-roi-editor) 复制以下示例:
holoviews 1.13.2
numpy 1.16.4
xarray 0.14.1
<xarray.Dataset>
Dimensions: (time: 1589, x: 50, y: 50)
Coordinates:
* x (x) float64 4.067e+05 4.067e+05 4.068e+05 ... 4.081e+05 4.082e+05
* y (y) float64 -1.309e+06 -1.309e+06 ... -1.311e+06 -1.311e+06
* time (time) datetime64[ns] 1988-01-04T00:33:06.940187 ... 2019-08-22T00:45:24.121949944
Data variables:
evi (time, y, x) float32 ...
polys = hv.Polygons([])
box_stream = streams.BoxEdit(source=polys)
def roi_curves(data):
if not data or not any(len(d) for d in data.values()):
return hv.NdOverlay({0: hv.Curve([], 'time', 'evi')})
curves = {}
data = zip(data['x0'], data['x1'], data['y0'], data['y1'])
for i, (x0, x1, y0, y1) in enumerate(data):
selection = hv_ds.select(x=(x0, x1), y=(y0, y1))
curves[i] = hv.Curve(selection.aggregate('time', np.mean))
return hv.NdOverlay(curves)
hlines = hv.HoloMap({i: hv.VLine(i) for i in range(2000)}, 'time')
dmap = hv.DynamicMap(roi_curves, streams=[box_stream])
(im * polys + dmap ).opts(
opts.Curve(width=400, framewise=True),
opts.Polygons(fill_alpha=0.2, line_color='white'),
opts.VLine(color='black'))
当我使用 (im * polys + dmap * hlines)
而不是 (im * polys + dmap)
时出现问题
使用 (im * polys + dmap)
的结果接近网站的结果,但缺少代表 time
维度的垂直黑线。
当我使用 (im * polys + dmap * hlines)
时,如 holoviews 示例所示,我得到:TypeError: invalid type promotion
,并且控制台打印以下内容:
...
~\Anaconda3\lib\site-packages\panel\pane\holoviews.py in widgets_from_dimensions(cls, object, widget_types, widgets_type)
395 if vals:
396 if all(isnumeric(v) or isinstance(v, datetime_types) for v in vals) and len(vals) > 1:
--> 397 vals = sorted(vals)
398 labels = [unicode(dim.pprint_value(v)) for v in vals]
399 options = OrderedDict(zip(labels, vals))
TypeError: invalid type promotion
:Layout
.DynamicMap.I :DynamicMap [time]
.DynamicMap.II :DynamicMap [time]
我认为问题出在 hlines
的定义中,因此 我已经尝试 更改 range(2000)
许多其他值,包括长度im
和 hv_ds
中的 time
维度,但错误非常神秘,我不知道如何调试它。
问题: 如何绘制代表 time
维度的垂直线,如 Holoviews 示例中所示?
正如您正确地发现这里的问题是 VLine HoloMap 的整数值。获取正确值的最简单方法是在图像堆栈上使用 .apply
方法,它构建了一个管道并允许您从图像中获取当前时间值。还需要进行一些其他修改才能使其与日期时间一起使用,例如我们必须声明一个空数据集,以便它使用正确的数据类型进行初始化。这是我的尝试:
import numpy as np
import pandas as pd
import xarray as xr
from holoviews import opts
# Create fake dataset
coords={'x': np.arange(50), 'y': np.arange(50),
'time': np.array([1514764800000000000+86400000000000*i for i in range(1589)]).astype('datetime64[ns]')}
evi = xr.DataArray(np.random.rand(50, 50, 1589), coords=coords, dims=['x', 'y', 'time'], name='evi')
hv_ds = hv.Dataset(evi)
# Create stack of images grouped by time
im = hv_ds.to(hv.Image, ['x', 'y'], dynamic=True)
polys = hv.Polygons([])
box_stream = hv.streams.BoxEdit(source=polys)
# Declare an empty DataFrame to declare the types
empty = pd.DataFrame({'time': np.array([], dtype='datetime64[ns]'), 'evi': []})
def roi_curves(data):
if not data or not any(len(d) for d in data.values()):
return hv.NdOverlay({0: hv.Curve(empty, 'time', 'evi')})
curves = {}
data = zip(data['x0'], data['x1'], data['y0'], data['y1'])
for i, (x0, x1, y0, y1) in enumerate(data):
selection = hv_ds.select(x=(x0, x1), y=(y0, y1))
curves[i] = hv.Curve(selection.aggregate('time', np.mean))
return hv.NdOverlay(curves)
# Generate VLines by getting time value from the image frames
def vline(frame):
return hv.VLine(frame.data.time.values)
vlines = im.apply(vline)
dmap = hv.DynamicMap(roi_curves, streams=[box_stream])
(im * polys + dmap * vlines ).opts(
opts.Curve(width=400, framewise=True),
opts.Polygons(fill_alpha=0.2, line_color='white'),
opts.VLine(color='black'))