Repository: holoviz/holoviews

Issue:
Using .redim.defaults overrides other Dimension attributes
As [discussed on StackOverflow](https://stackoverflow.com/questions/55092912/specifying-the-default-value-in-widgets-generated-by-pyviz-hvplot), it would be nice to be able to specify the default values for widgets created automatically by `hvplot`. 

I've got a 4D dataset and `hvplot` is nicely generating widgets for the dimensions I've specified in the `groupby`:
```python
import xarray as xr

ds = xr.open_dataset('http://gamone.whoi.edu/thredds/dodsC/coawst_4/use/fmrc/coawst_4_use_best.ncd')

rho_vars = ['salt','temp']

from cartopy import crs as ccrs
import hvplot.xarray
import holoviews as hv
from geoviews import tile_sources as gvts
import panel as pn

var_select = pn.widgets.Select(name='Variables:', options=rho_vars, 
                               value='temp')

crs = ccrs.PlateCarree()

def plot(var=None):
    base_map = gvts.OSM
    var = var or var_select.value
    mesh = ds[var][-24:,:,:].hvplot.quadmesh(x='lon_rho', y='lat_rho', rasterize=True, title=var,
                                    width=600, height=400, crs=crs,
                                    groupby=list(ds[var].dims[:-2]), cmap='jet')
    overlay = (base_map * mesh.opts(alpha=0.7)).opts(active_tools=['wheel_zoom', 'pan'])
    widgets = {dim: pn.widgets.Select for dim in ds[var].dims[:-2]}
    return pn.holoviews.HoloViews(overlay, widgets=widgets).layout

def on_var_select(event):
    var = event.obj.value
    dashboard[-1] = plot(var=var)

var_select.param.watch(on_var_select, parameter_names=['value']);

dashboard = pn.Column(var_select, plot(var_select.value))
```
which produces:
![one](https://user-images.githubusercontent.com/1872600/54302289-fafff480-4596-11e9-9ad4-bd1f9a3fd4de.png)

However, while `hvplot` defaults to the *first* value of the `options` in the `OrderedDict`, I would like to default to the *last* value.

If I look at the dashboard elements:
```python
    print(dashboard)

    Column
        [0] Select(name='Variables:', options=OrderedDict([('salt', ...]), value='temp')
        [1] Row
            [0] HoloViews(DynamicMap, widgets={'time': <class 'panel.wid...})
            [1] Column
                [0] Select(name='Forecast time f..., options=OrderedDict([('2019-03-09 ...]), value=numpy.datetime64('2019-03-...)
                [1] Select(name='S-coordinate a..., options=OrderedDict([('-0.96875', ...]), value=-0.96875)
```
I see that I can specify the `Select` widget value *post facto* like:
```python
dashboard[1][1][1].value = next(reversed(dashboard[1][1][1].options.values())) 
```
and that indeed works:
![two](https://user-images.githubusercontent.com/1872600/54302450-40242680-4597-11e9-8eae-e2db19192df5.png)

I would like to make a stand alone dashboard, however, that defaults to a last value when the user selects a new variable.  With the current code, when a new variable is selected, the default value is unfortunately again set to the first value. 

Is there a way to embed my *post facto* code to select the last value into my plot function, or is there another better approach to accomplish this?

The full notebook is here: https://nbviewer.jupyter.org/gist/rsignell-usgs/edb9eb572058c4fdee6708359d24539d


Discussion:
Still thinking about a good solution for this issue, passing in widget instances rather than classes works but is not very convenient. The easiest approach for now may be to set the dimension default on the HoloViews object using ``.redim.default``, i.e. something likes this:

```python
mesh = mesh.redim.default(**{d: ds[d].max() for d in ds[var].dims[:-2]})
```

In the longer term I'd like to continue thinking about ways to improve the way this can be specified in panel.
@philippjfr, I'm still not sure how to use this.   I tried add that line just after the mesh creation in my plot function, but when I try to render I get:
```
SkipRendering: DynamicMap cannot be displayed without explicit indexing as 'time', 's_rho' dimension(s) are unbounded. 
Set dimensions bounds with the DynamicMap redim.range or redim.values methods.
```
From my reading of the [Holoviews Live Data docs](http://holoviews.org/user_guide/Live_Data.html) it would seem somehow the dimension values are getting lost during the `redim.default` assignment.
```python
import xarray as xr
import hvplot.xarray
import panel as pn

ds = xr.tutorial.open_dataset('air_temperature').load()
var = 'air'
atemp = ds[var][:10,:,:]
mesh = atemp.hvplot(groupby='time')
```
![2019-03-15_11-30-42](https://user-images.githubusercontent.com/1872600/54442886-de3dfb00-4715-11e9-996b-7666894353d1.png)
```python
mesh = mesh.redim.default(**{d: ds[d].max() for d in ds[var].dims[:-2]})
```
![2019-03-15_11-32-01](https://user-images.githubusercontent.com/1872600/54442981-11808a00-4716-11e9-8b5d-0a1821250397.png)



Yeah this is starting to sound like a HoloViews bug. Separately though I think I've decided that the ``widgets`` dictionary argument to panel should accept dictionaries with partial overrides, i.e. I would like something like this to work:

```python
widgets = {dim: {'value': ds[dim].max()} for dim in ds[var].dims[:-2]}
return pn.holoviews.HoloViews(overlay, widgets=widgets).layout
```
I'm going to transfer this issue over to holoviews since the HoloViews pane now support something like this:

```python
widgets = {dim: {'type: pn.widget.Select, 'value': ds[dim].max()} for dim in ds[var].dims[:-2]}
return pn.holoviews.HoloViews(overlay, widgets=widgets).layout
```

Resolving patch:
diff --git a/holoviews/core/dimension.py b/holoviews/core/dimension.py
--- a/holoviews/core/dimension.py
+++ b/holoviews/core/dimension.py
@@ -325,7 +325,7 @@ def clone(self, spec=None, **overrides):
         Returns:
             Cloned Dimension object
         """
-        settings = dict(self.get_param_values(onlychanged=True), **overrides)
+        settings = dict(self.get_param_values(), **overrides)
 
         if spec is None:
             spec = (self.name, overrides.get('label', self.label))
@@ -337,7 +337,6 @@ def clone(self, spec=None, **overrides):
                     'Using label as supplied by keyword ({!r}), ignoring '
                     'tuple value {!r}'.format(overrides['label'], spec[1]))
             spec = (spec[0],  overrides['label'])
-
         return self.__class__(spec, **{k:v for k,v in settings.items()
                                        if k not in ['name', 'label']})
 


Test patch: