import os, numpy as np, pandas as pd, cartopy.crs as ccrs, bokeh import holoviews as hv, geoviews as gv, datashader as ds from colorcet import bmy from holoviews.util import Dynamic from holoviews.operation.datashader import rasterize, datashade hv.extension('bokeh', width=100) df = pd.read_csv('data/oggm_glacier_explorer.csv') df['latdeg'] = df.cenlat df.tail() data = gv.Points(df, [('cenlon', 'Longitude'), ('cenlat', 'Latitude')], [('avg_prcp', 'Annual Precipitation (mm/yr)'), ('area_km2', 'Area'), ('latdeg', 'Latitude (deg)'), ('avg_temp_at_mean_elev', 'Annual Temperature at avg. altitude'), ('mean_elev', 'Elevation')]) total_area = df.area_km2.sum() print(data, len(data), total_area) data = gv.Dataset(gv.operation.project_points(data)) geo_kw = dict(aggregator=ds.sum('area_km2'), x_sampling=1000, y_sampling=1000) elev_kw = dict(cmap='#7d3c98') temp_kw = dict(num_bins=50, adjoin=False, normed=False, bin_range=data.range('avg_temp_at_mean_elev')) prcp_kw = dict(num_bins=50, adjoin=False, normed=False, bin_range=data.range('avg_prcp')) size_opts = dict(min_height=400, min_width=600, responsive=True) geo_opts = dict(size_opts, cmap=bmy, global_extent=False, logz=True, colorbar=True) elev_opts = dict(size_opts, show_grid=True) temp_opts = dict(size_opts, fill_color='#f1948a', default_tools=[], toolbar=None, alpha=1.0) prcp_opts = dict(size_opts, fill_color='#85c1e9', default_tools=[], toolbar=None, alpha=1.0) geo_bg = gv.tile_sources.EsriImagery.options(alpha=0.6, bgcolor="black") geopoints = data.to(gv.Points, ['cenlon', 'cenlat'], ['area_km2'], []).options(**geo_opts).redim.range(area_km2=(0, 3000)) (geo_bg*rasterize(geopoints, **geo_kw).options(**geo_opts) + datashade(data.to(hv.Scatter, 'mean_elev','latdeg', []), **elev_kw).options(**elev_opts) + data.hist('avg_temp_at_mean_elev', **temp_kw).options(**temp_opts) + data.hist('avg_prcp', **prcp_kw).options(**prcp_opts)).cols(2) def geo(data): return gv.Points(data, crs=ccrs.GOOGLE_MERCATOR).options(alpha=1) def elev(data): return data.to(hv.Scatter, 'mean_elev', 'latdeg', []) def temp(data): return data.hist('avg_temp_at_mean_elev', **temp_kw).options(**temp_opts) def prcp(data): return data.hist('avg_prcp', **prcp_kw).options(**prcp_opts) def count(data): return hv.Div('
Glaciers selected: {}'.format(len(data)) + "
" +
'Area: {:.0f} kmĀ² ({:.1f}%)'.format(np.sum(data['area_km2']), np.sum(data['area_km2']) / total_area * 100)).options(height=40)
static_geo = rasterize(geo(data), **geo_kw).options(alpha=0.1, tools=['hover', 'box_select'], active_tools=['box_select'], **geo_opts)
static_elev = datashade(elev(data), **elev_kw).options(alpha=0.1, tools=[ 'box_select'], active_tools=['box_select'], **elev_opts)
static_temp = temp(data).options(alpha=0.1)
static_prcp = prcp(data).options(alpha=0.1)
def combine_selections(**kwargs):
"""
Combines selections on all available plots into a single selection by index.
"""
if all(not v for v in kwargs.values()):
return slice(None)
selection = {}
for key, bounds in kwargs.items():
if bounds is None:
continue
elif len(bounds) == 2:
selection[key] = bounds
else:
xbound, ybound = key.split('__')
selection[xbound] = bounds[0], bounds[2]
selection[ybound] = bounds[1], bounds[3]
return sorted(set(data.select(**selection).data.index))
def select_data(**kwargs):
return data.iloc[combine_selections(**kwargs)] if kwargs else data
select_data(cenlon__cenlat=(3000000, 9000000, 5000000, 11000000)).dframe()
select_data(cenlon__cenlat=(3000000, 9000000, 5000000, 11000000), avg_temp_at_mean_elev=(-5,-2)).dframe()
from holoviews.streams import Stream, BoundsXY, BoundsX
geo_bounds = BoundsXY(source=static_geo, rename={'bounds': 'cenlon__cenlat'})
elev_bounds = BoundsXY(source=static_elev, rename={'bounds': 'mean_elev__latdeg'})
temp_bounds = BoundsX( source=static_temp, rename={'boundsx': 'avg_temp_at_mean_elev'})
prcp_bounds = BoundsX( source=static_prcp, rename={'boundsx': 'avg_prcp'})
selections = [geo_bounds, elev_bounds, temp_bounds, prcp_bounds]
dyn_data = hv.DynamicMap(select_data, streams=selections)
dyn_geo = rasterize(dyn_data.apply(geo), **geo_kw).options( **geo_opts)
dyn_elev = datashade(dyn_data.apply(elev), **elev_kw).options(**elev_opts)
dyn_temp = dyn_data.apply(temp)
dyn_prcp = dyn_data.apply(prcp)
dyn_count = dyn_data.apply(count)
geomap = geo_bg * static_geo * dyn_geo
elevation = static_elev * dyn_elev
temperature = static_temp * dyn_temp
precipitation = static_prcp * dyn_prcp
def clear_selections(arg=None):
geo_bounds.update(bounds=None)
elev_bounds.update(bounds=None)
temp_bounds.update(boundsx=None)
prcp_bounds.update(boundsx=None)
Stream.trigger(selections)
import panel as pn
pn.extension()
clear_button = pn.widgets.Button(name='Clear selection')
clear_button.param.watch(clear_selections, 'clicks');
title = '