Repository: https://github.com/jupyter-widgets/ipyleaflet

Installation:

conda install -c conda-forge ipyleaflet

Base map


In [1]:
from ipyleaflet import Map, basemaps, basemap_to_tiles

In [2]:
center = (52.204793, 360.121558)

m = Map(
    layers=(basemap_to_tiles(basemaps.NASAGIBS.ModisTerraTrueColorCR, "2018-11-12"), ),
    center=center,
    zoom=4
)

m


Layers

Marker


In [3]:
from ipyleaflet import Marker, Icon

icon = Icon(icon_url='https://leafletjs.com/examples/custom-icons/leaf-red.png', icon_size=[38, 95], icon_anchor=[22,94])
mark = Marker(location=center, icon=icon, rotation_origin='22px 94px')

m.add_layer(mark)

In [4]:
import time

for _ in range(40):
    mark.rotation_angle += 15
    time.sleep(0.1)

Repository: https://github.com/jupyter-widgets/jupyterlab-sidecar

Installation:

pip install jupyterlab_sidecar


In [5]:
from sidecar import Sidecar
from IPython.display import display

In [6]:
sc = Sidecar(title='Map widget')

with sc:
    display(m)

Heatmap layer


In [7]:
from ipywidgets import Button, IntSlider, link
from ipyleaflet import Heatmap
from random import gauss
import time

In [8]:
center = (37.09, -103.66)
zoom = 5

In [9]:
def create_random_data(length):
    "Return a list of some random lat/lon/value triples."
    return [[gauss(center[0], 2), 
             gauss(center[1], 4),
             gauss(700, 300)] for i in range(length)]

In [10]:
m.center = center
m.zoom = zoom

In [11]:
heat = Heatmap(locations=create_random_data(1000), radius=20, blur=10)
m.add_layer(heat)

In [12]:
def generate(_):
    heat.locations = create_random_data(1000)

button = Button(description='Generate data', button_style='success')
button.on_click(generate)
button



In [13]:
slider = IntSlider(min=10, max=30, value=heat.radius)
link((slider, 'value'), (heat, 'radius'))
slider


Velocity


In [14]:
from ipyleaflet import Velocity
import xarray as xr

In [15]:
center = (0, 0)
zoom = 4

m2 = Map(center=center, zoom=zoom, interpolation='nearest', basemap=basemaps.CartoDB.DarkMatter)

sc2 = Sidecar(title='Map Velocity')

with sc2:
    display(m2)

In [16]:
ds = xr.open_dataset('src/wind-global.nc')
display_options = {
    'velocityType': 'Global Wind',
    'displayPosition': 'bottomleft',
    'displayEmptyString': 'No wind data'
}
wind = Velocity(data=ds,
                zonal_speed='u_wind',
                meridional_speed='v_wind',
                latitude_dimension='lat',
                longitude_dimension='lon',
                velocity_scale=0.01,
                max_velocity=20,
                display_options=display_options)
m2.add_layer(wind)


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~/miniconda3/lib/python3.7/site-packages/xarray/backends/scipy_.py in _open_scipy_netcdf(filename, mode, mmap, version)
     92         return scipy.io.netcdf_file(filename, mode=mode, mmap=mmap,
---> 93                                     version=version)
     94     except TypeError as e:  # netcdf3 message is obscure in this case

~/miniconda3/lib/python3.7/site-packages/scipy/io/netcdf.py in __init__(self, filename, mode, mmap, version, maskandscale)
    283         if mode in 'ra':
--> 284             self._read()
    285 

~/miniconda3/lib/python3.7/site-packages/scipy/io/netcdf.py in _read(self)
    608             raise TypeError("Error: %s is not a valid NetCDF 3 file" %
--> 609                             self.filename)
    610         self.__dict__['version_byte'] = frombuffer(self.fp.read(1), '>b')[0]

TypeError: Error: /home/sylvain/dev/QuantStack/quantstack-talks/ESRF/notebooks/src/wind-global.nc is not a valid NetCDF 3 file

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
<ipython-input-16-e68385d0ed19> in <module>
----> 1 ds = xr.open_dataset('src/wind-global.nc')
      2 display_options = {
      3     'velocityType': 'Global Wind',
      4     'displayPosition': 'bottomleft',
      5     'displayEmptyString': 'No wind data'

~/miniconda3/lib/python3.7/site-packages/xarray/backends/api.py in open_dataset(filename_or_obj, group, decode_cf, mask_and_scale, decode_times, autoclose, concat_characters, decode_coords, engine, chunks, lock, cache, drop_variables, backend_kwargs)
    322             store = backends.ScipyDataStore(filename_or_obj,
    323                                             autoclose=autoclose,
--> 324                                             **backend_kwargs)
    325         elif engine == 'pydap':
    326             store = backends.PydapDataStore.open(filename_or_obj,

~/miniconda3/lib/python3.7/site-packages/xarray/backends/scipy_.py in __init__(self, filename_or_obj, mode, format, group, writer, mmap, autoclose, lock)
    144                                    filename=filename_or_obj,
    145                                    mode=mode, mmap=mmap, version=version)
--> 146         self._ds = opener()
    147         self._autoclose = autoclose
    148         self._isopen = True

~/miniconda3/lib/python3.7/site-packages/xarray/backends/scipy_.py in _open_scipy_netcdf(filename, mode, mmap, version)
    102             """
    103             errmsg += msg
--> 104             raise TypeError(errmsg)
    105         else:
    106             raise

TypeError: Error: /home/sylvain/dev/QuantStack/quantstack-talks/ESRF/notebooks/src/wind-global.nc is not a valid NetCDF 3 file
            If this is a NetCDF4 file, you may need to install the
            netcdf4 library, e.g.,

            $ pip install netcdf4
            

Controls


In [17]:
from ipyleaflet import Map, basemaps, basemap_to_tiles, SplitMapControl

m = Map(center=(42.6824, 365.581), zoom=5)

right_layer = basemap_to_tiles(basemaps.NASAGIBS.ModisTerraTrueColorCR, "2017-11-11")
left_layer = basemap_to_tiles(basemaps.NASAGIBS.ModisAquaBands721CR, "2017-11-11")

control = SplitMapControl(left_layer=left_layer, right_layer=right_layer)
m.add_control(control)

m


Plays well with other widgets libraries


In [18]:
import numpy as np
import bqplot.pyplot as plt
from bqplot import *
from traitlets import observe
from sidecar import Sidecar
from ipywidgets import VBox, Button
from ipyleaflet import Map, Marker, Popup

In [19]:
axes_options = {'x': {'label': 'x'}, 'y': {'label': 'y'}}

x = np.arange(40)
y = np.cumsum(np.random.randn(2, 40), axis=1)

fig = plt.figure(animation_duration=1000)
lines = plt.plot(x=x, y=y, colors=['red', 'green'], axes_options=axes_options)

def generate(_):
    lines.y = np.cumsum(np.random.randn(2, 40), axis=1)

button = Button(description='Generate data', button_style='success')
button.on_click(generate)

box_plot = VBox([fig, button])

fig



In [20]:
center = (52.204793, 360.121558)

m = Map(center=center, zoom=9, close_popup_on_click=False)

marker = Marker(location=(52.1, 359.9))
m.add_layer(marker)

marker.popup = box_plot

sc = Sidecar(title='Map and bqplot')

with sc:
    display(m)

Clean


In [21]:
from ipywidgets import Widget
Widget.close_all()

Example: ipyleaflet application using qgrid and bqplot


In [ ]: