From 9d2a8dab77002b13112223b249d30ce499446e1c Mon Sep 17 00:00:00 2001 From: Andrew <15331990+ahuang11@users.noreply.github.com> Date: Tue, 16 Jul 2024 07:20:48 -0700 Subject: [PATCH] Make explorer geo more optimized (#1353) --- hvplot/tests/testui.py | 7 +++++ hvplot/ui.py | 65 +++++++++++++++++++++++------------------- 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/hvplot/tests/testui.py b/hvplot/tests/testui.py index 035fe09d8..3bd160701 100644 --- a/hvplot/tests/testui.py +++ b/hvplot/tests/testui.py @@ -388,3 +388,10 @@ def test_explorer_xarray_multi_var_extra_dims_no_coord(): ds = xr.tutorial.open_dataset('air_temperature') ds['lat_bnds'] = (('bnds', 'lat'), np.vstack([ds['lat'], ds['lat']])) assert ds.hvplot.explorer() + + +@pytest.mark.parametrize('kind_tuple', [('scatter', 'points'), ('line', 'paths')]) +def test_explorer_geo_revise_kind(kind_tuple): + da = ds_air_temperature['air'].isel(time=0) + explorer = hvplot.explorer(da, x='lon', y='lat', kind=kind_tuple[0], geo=True) + assert explorer.kind == kind_tuple[1] diff --git a/hvplot/ui.py b/hvplot/ui.py index ee6f260b0..45411fe20 100644 --- a/hvplot/ui.py +++ b/hvplot/ui.py @@ -19,14 +19,14 @@ set(_hvConverter._kind_mapping) - set(_hvConverter._gridded_types) - set(_hvConverter._geom_types) - | set(['points']) + | set(['points', 'paths']) ), 'gridded': sorted(set(_hvConverter._gridded_types) - set(['dataset'])), 'geom': _hvConverter._geom_types, } KINDS['2d'] = ( - ['bivariate', 'heatmap', 'hexbin', 'labels', 'vectorfield', 'points'] + ['bivariate', 'heatmap', 'hexbin', 'labels', 'vectorfield', 'points', 'paths'] + KINDS['gridded'] + KINDS['geom'] ) @@ -383,37 +383,43 @@ def __init__(self, data, **params): @param.depends('geo', watch=True) def _update_crs_projection(self): - enabled = bool(self.geo or self.project) - for key in GEO_KEYS: - self.param[key].constant = not enabled - self.geo = enabled - if not enabled: - return + with param.parameterized.batch_call_watchers(self): + enabled = bool(self.geo or self.project) + for key in GEO_KEYS: + self.param[key].constant = not enabled + self.geo = enabled + if not enabled: + return + + from cartopy.crs import CRS + + crs_list = sorted( + k + for k in param.concrete_descendents(CRS).keys() + if not k.startswith('_') and k != 'CRS' + ) + crs_list.insert(0, 'GOOGLE_MERCATOR') + crs_list.insert(0, 'PlateCarree') + crs_list.remove('PlateCarree') - from cartopy.crs import CRS + if self.explorer.kind == 'scatter': + self.explorer.kind = 'points' + elif self.explorer.kind == 'line': + self.explorer.kind = 'paths' - crs_list = sorted( - k - for k in param.concrete_descendents(CRS).keys() - if not k.startswith('_') and k != 'CRS' - ) - crs_list.insert(0, 'GOOGLE_MERCATOR') - crs_list.insert(0, 'PlateCarree') - crs_list.remove('PlateCarree') + self.param.crs.objects = crs_list + self.param.projection.objects = crs_list + updates = {} + if self.projection is None: + updates['projection'] = crs_list[0] - self.param.crs.objects = crs_list - self.param.projection.objects = crs_list - updates = {} - if self.projection is None: - updates['projection'] = crs_list[0] + if self.global_extent is None: + updates['global_extent'] = True - if self.global_extent is None: - updates['global_extent'] = True + if self.features is None: + updates['features'] = ['coastline'] - if self.features is None: - updates['features'] = ['coastline'] - - self.param.update(**updates) + self.param.update(**updates) class Operations(Controls): @@ -670,9 +676,10 @@ def _plot(self): self.geographic.crs = 'PlateCarree' if xmax <= 360 else 'GOOGLE_MERCATOR' kwargs['crs'] = self.geographic.crs for key in ['crs', 'projection']: + if key not in kwargs: + continue crs_kwargs = kwargs.pop(f'{key}_kwargs', {}) kwargs[key] = instantiate_crs_str(kwargs.pop(key), **crs_kwargs) - feature_scale = kwargs.pop('feature_scale', None) kwargs['features'] = {feature: feature_scale for feature in kwargs.pop('features', [])}