<jupyter_start><jupyter_text>Exploring `hvplot`PyViz released a library called `hvplot` as a high-level plotting API for the PyData ecosystem.This is a reproduction of the example in this [blogpost](http://blog.pyviz.org/hvplot_announcement.htmlSupport-for-geographic-plots) and to see whether it can be extended with other `bokeh` tools such as [`FreehandDraw`](https://bokeh.pydata.org/en/latest/docs/user_guide/tools.htmlfreehanddrawtool).  Demo<jupyter_code>import hvplot as hplt
import xarray as xr
import hvplot.xarray
import geoviews as gv
import cartopy.crs as ccrs
import cartopy.feature as cf<jupyter_output><empty_output><jupyter_text>Load a dataset using `xarray`<jupyter_code>air_ds = xr.tutorial.open_dataset('air_temperature').load()
air_ds<jupyter_output><empty_output><jupyter_text>Define all the elements of our plot<jupyter_code>coastlines = gv.feature.coastline
proj = ccrs.Orthographic(-90, 30)
air_temp = air_ds.air.isel(time=slice(0, 9, 3))
air_plot = air_temp.hvplot.quadmesh(
    'lon', 'lat', projection=proj, project=True, global_extent=True,
    width=600, height=540, cmap='viridis', rasterize=True, dynamic=False)<jupyter_output><empty_output><jupyter_text>Combine and display our plot elements<jupyter_code>air_plot * coastlines<jupyter_output><empty_output><jupyter_text>Cool, that works as expected.  `bokeh` vs `matplotlib` Compare that to plotting with a `matplotlib` backend<jupyter_code>import holoviews as hv

hv.extension('matplotlib')

air_plot_mpl = air_temp.hvplot.quadmesh(
    'lon', 'lat', projection=proj, project=True, global_extent=True,
    width=600, height=540, cmap='viridis', rasterize=True, dynamic=False)

air_plot_mpl * coastlines<jupyter_output><empty_output><jupyter_text>Compare **that** to plotting with just `matplotlib`<jupyter_code>%matplotlib inline
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(12, 12))
ax = fig.add_subplot(111, projection=ccrs.Orthographic(-90, 30))
ax.set_global()
air_temp.isel(time=0).plot.pcolormesh(ax=ax, transform=ccrs.PlateCarree())
ax.coastlines()<jupyter_output><empty_output><jupyter_text>Extending `hvplot` example A `FreehandDraw` tool must be linked to another element, in this case a `Path`<jupyter_code>import geoviews as gv
from holoviews.streams import FreehandDraw

hv.extension('bokeh')

draw_tool = gv.Path([]).opts(color='magenta', line_width=4)
freehand_stream = FreehandDraw(source=draw_tool)<jupyter_output><empty_output><jupyter_text>Let's combine those and test it out<jupyter_code>air_plot * coastlines * draw_tool<jupyter_output><empty_output><jupyter_text>Yasssss, it works! We can draw lines on our plotted data.  Q: Can we now get hold of the scribbles we have made?<jupyter_code>freehand_stream.element
print(freehand_stream.element)
freehand_stream.data
draw_tool.data<jupyter_output><empty_output><jupyter_text>Yes we can! From the tool object itself (`freehand_stream`) we can get the information of a scribble back as a `HoloViews` element or the actual `(x,y)` data in lat and lon i.e. georeferencing for free!  Q: Can we add multiple pens for the forecasters to use?<jupyter_code>cold_front = gv.Path([]).opts(color='blue', line_width=4)
cold_front_pen = FreehandDraw(source=cold_front)

warm_front = gv.Path([]).opts(color='red', line_width=4)
warm_front_pen = FreehandDraw(source=warm_front)
air_plot * coastlines * warm_front * cold_front
warm_front_pen.element
cold_front_pen.element
warm_front_pen.data<jupyter_output><empty_output><jupyter_text>Yep, multiple instances of the same tool (`FreehandDraw`) can be linked to different `Path`s, each with different properties.**Development goals:**1. Store more useful metadata with the path2. Change the icon for each brush. Just color to start with but then more useful symbols.  Q: Can we add a warning area polyon tool?<jupyter_code>warning_orange = gv.Polygons([]).opts(line_color='orange', line_width=4, 
                                      fill_color='orange', fill_alpha=0.6)
warning_orange_tool = FreehandDraw(source=warning_orange)
air_plot * coastlines * warning_orange
warning_orange_tool.element<jupyter_output><empty_output><jupyter_text>Polygons can be linked to the same freehand drawing tool. This will be useful for annotating with areas e.g. weather warnings.  Q: Can we reapply elements to a new plot?<jupyter_code>warning_01 = warning_orange_tool.element
air_temp_all = air_ds.air.isel(time=slice(0, 9, 1))
air_plot_all = air_temp_all.hvplot.quadmesh(
    'lon', 'lat', projection=proj, project=True, global_extent=True,
    width=600, height=540, cmap='fire', rasterize=True, dynamic=False)
air_plot_all * coastlines * warning_01<jupyter_output><empty_output><jupyter_text>Yes reapplication can be done. This will be useful for sharing and re-using annotation elements.  Q: Can an element be reapplied and edited?<jupyter_code>warning_02 = warning_orange_tool.element.opts(line_color='orange', line_width=1,
                                              fill_color='orange', fill_alpha=0.4)
from holoviews import streams
poly_edit = streams.PolyEdit(source=warning_02)
air_plot * coastlines * warning_02
from holoviews.streams import PolyEdit

cold_front_01 = cold_front_pen.element.opts(line_color='blue', line_width=2)

cold_front_edit = PolyEdit(source=cold_front_01)

cold_front_01
air_plot * coastlines * cold_front_01<jupyter_output><empty_output><jupyter_text>Elements can be reallied and edited. This includes restyling the element and linking it to the `PolyEdit` tool.  Q: Can interactive plot be launched in a `Sidecar`?<jupyter_code>from sidecar import Sidecar

with Sidecar():
    display(air_plot * coastlines * warm_front * cold_front * warning_orange)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09970212020325915, 'fraction_numerical': 0.012265638689328895, 'mean_word_length': 6.672043010752688, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 57, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '196834', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2029, 'n_tokens_neox': 1920, 'n_words': 471, 'path': 'hvplot.ipynb', 'repo_name': 'informatics-lab/annotable-bokeh', 'size': '5707'}