diff --git a/examples/user_guide/07-Live_Data.ipynb b/examples/user_guide/07-Live_Data.ipynb index 06d6188180..353380585f 100644 --- a/examples/user_guide/07-Live_Data.ipynb +++ b/examples/user_guide/07-Live_Data.ipynb @@ -214,9 +214,36 @@ "The sliders now snap to the specified dimension values and if you are running this live, the above cell should look like a [HoloMap](../reference/containers/bokeh/HoloMap.ipynb). ``DynamicMap`` is in fact a subclass of ``HoloMap`` with some crucial differences:\n", "\n", "* You can now pick as many values of **alpha** or **beta** as allowed by the slider.\n", - "* What you see in the cell above will not be exported in any HTML snapshot of the notebook\n", - "\n", - "\n", + "* What you see in the cell above will not be exported in any HTML snapshot of the notebook" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Getting the current key" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The ``current_key`` property returns the current key of the ``DynamicMap``, i.e. either a value (one-dimensional) or a tuple (multi-dimensional) that represents the current state of the widgets. If you move the sliders above and re-execute the cell below you will see that the tuple returned reflects the values of *alpha* and *beta*." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dmap.current_key" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "We will now explore how ``DynamicMaps`` relate to ``HoloMaps`` including conversion operations between the two types. As we will see, there are other ways to display a ``DynamicMap`` without using explicit indexing or redim." ] }, @@ -657,5 +684,5 @@ } }, "nbformat": 4, - "nbformat_minor": 1 + "nbformat_minor": 4 } diff --git a/holoviews/core/spaces.py b/holoviews/core/spaces.py index 0b00b66b62..560f97d62a 100644 --- a/holoviews/core/spaces.py +++ b/holoviews/core/spaces.py @@ -826,6 +826,8 @@ def __init__(self, callback, initial_items=None, streams=None, **params): self.periodic = periodic(self) + self._current_key = None + @property def opts(self): return Opts(self, mode='dynamicmap') @@ -853,6 +855,11 @@ def unbounded(self): unbounded_dims.append(str(kdim)) return unbounded_dims + @property + def current_key(self): + """Returns the current key value.""" + return self._current_key + def _stream_parameters(self): return util.stream_parameters( self.streams, no_duplicates=not self.positional_stream_args @@ -1170,6 +1177,8 @@ def __getitem__(self, key): otherwise returns cloned DynamicMap containing the cross- product of evaluated items. """ + self._current_key = key + # Split key dimensions and data slices sample = False if key is Ellipsis: diff --git a/holoviews/tests/core/test_dynamic.py b/holoviews/tests/core/test_dynamic.py index 51fb80ba35..62640ff5bb 100644 --- a/holoviews/tests/core/test_dynamic.py +++ b/holoviews/tests/core/test_dynamic.py @@ -543,6 +543,36 @@ def test_mixed_kdim_streams_bounded_redim(self): self.assertEqual(dmap.redim.range(z=(-0.5,0.5)).unbounded, []) +class DynamicMapCurrentKeyProperty(ComparisonTestCase): + + def test_current_key_None_on_init(self): + fn = lambda i: Image(sine_array(0,i)) + dmap = DynamicMap(fn, kdims=[Dimension('dim', range=(0,10))]) + self.assertIsNone(dmap.current_key) + + def test_current_key_one_dimension(self): + fn = lambda i: Image(sine_array(0,i)) + dmap=DynamicMap(fn, kdims=[Dimension('dim', range=(0,10))]) + dmap[0] + self.assertEqual(dmap.current_key, 0) + dmap[1] + self.assertEqual(dmap.current_key, 1) + dmap[0] + self.assertEqual(dmap.current_key, 0) + self.assertNotEqual(dmap.current_key, dmap.last_key) + + def test_current_key_multiple_dimensions(self): + fn = lambda i, j: Curve([i, j]) + dmap=DynamicMap(fn, kdims=[Dimension('i', range=(0,5)), Dimension('j', range=(0,5))]) + dmap[0, 2] + self.assertEqual(dmap.current_key, (0, 2)) + dmap[5, 5] + self.assertEqual(dmap.current_key, (5, 5)) + dmap[0, 2] + self.assertEqual(dmap.current_key, (0, 2)) + self.assertNotEqual(dmap.current_key, dmap.last_key) + + class DynamicTransferStreams(ComparisonTestCase): def setUp(self):