class BasemapTool: """Widget for switching between different basemaps (TileLayers). This will not work in combination with `ipyleaflet.SplitMapControl`. """ def __init__(self, description: str = "Basemap", position: str = "topright", a_map: Map = None): options = list(yield_basemap_dicts()) options = [opt["name"] for opt in options] current_basemap_name = [ l for l in a_map.layers if type(l) == TileLayer ][0].name start_value = current_basemap_name if current_basemap_name in options else options[ 0] dropdown = Dropdown(description=description, options=options, value=start_value, layout=Layout(width="250px")) close_btn = Button( icon="times", button_style="info", tooltip="Close the basemap widget", layout=Layout(width="32px"), ) self.widget = HBox([dropdown, close_btn]) def switch(basemap_name): if len(a_map.layers) == 1: a_map.layers = tuple([TileLayer(**get_basemap(basemap_name))]) else: old_basemap = [ l for l in a_map.layers if type(l) == TileLayer ][0] a_map.substitute_layer(old_basemap, TileLayer(**get_basemap(basemap_name))) def on_click(change): basemap_name = change["new"] switch(basemap_name) dropdown.observe(on_click, "value") def close_click(change): if a_map.basemap_ctrl is not None and a_map.basemap_ctrl in a_map.controls: a_map.remove_control(a_map.basemap_ctrl) self.widget.close() close_btn.on_click(close_click) self.widget_control = WidgetControl(widget=self.widget, position="topright") a_map.add_control(self.widget_control) a_map.basemap_ctrl = self.widget_control switch(dropdown.value)
class NBProgressBar(ProgressBar): def __init__(self, gen, total=None, display=True, leave=True, parent=None, auto_update=True): self.progress, self.text = IntProgress( min=0, max=len(gen) if total is None else total), HTML() self.box = HBox([self.progress, self.text]) super().__init__(gen, total, display, leave, parent, auto_update) def on_iter_begin(self): if self.display: display(self.box) self.is_active = True def on_interrupt(self): self.progress.bar_style = 'danger' self.is_active = False def on_iter_end(self): if not self.leave: self.box.close() self.is_active = False def on_update(self, val, text): self.text.value = text self.progress.value = val
class ProgressIPy(ProgressBase): # pragma: no cover HTMLBOX = '<div class="widget-hbox widget-progress"><div class="widget-label" style="display:block;">{0}</div></div>' def __init__(self, *args, **kargs): # Ipython gives warnings when using widgets about the API potentially changing with warnings.catch_warnings(): warnings.simplefilter("ignore") try: from ipywidgets import HTML, HBox, IntProgress except ImportError: # Support IPython < 4.0 from IPython.html.widgets import HTML, HBox, IntProgress super().__init__(*args, **kargs) self.prog = IntProgress(max=self.length) self._label = HTML() self._box = HBox((self.prog, self._label)) def start(self): from IPython.display import display display(self._box) super().start() @property def value(self): """This is the current value, -1 allowed (automatically fixed for display)""" return self._value @value.setter def value(self, val): self._value = val self.prog.value = max(val, 0) self.prog.description = f"{self.value / self.length:.2%}" if self.timer and val > 0: self._label.value = self.HTMLBOX.format(self.str_time_remaining()) def display(self): pass def done(self): if self.clear: self._box.close()
class ProgressIPy(ProgressBase): # pragma: no cover HTMLBOX = '<div class="widget-hbox widget-progress"><div class="widget-label" style="display:block;">{0}</div></div>' def __init__(self, *args, **kargs): # Ipython gives warnings when using widgets about the API potentially changing with warnings.catch_warnings(): warnings.simplefilter("ignore") try: from ipywidgets import IntProgress, HTML, HBox # type: ignore except ImportError: # Support IPython < 4.0 from IPython.html.widgets import IntProgress, HTML, HBox # type: ignore super(ProgressIPy, self).__init__(*args, **kargs) self.prog = IntProgress(max=self.length) self._label = HTML() self._box = HBox((self.prog, self._label)) def start(self): from IPython.display import display # type: ignore display(self._box) super(ProgressIPy, self).start() @property def value(self): """This is the current value, -1 allowed (automatically fixed for display)""" return self._value @value.setter def value(self, val): self._value = val self.prog.value = max(val, 0) self.prog.description = "{0:.2%}".format(self.value / self.length) if self.timer and val > 0: self._label.value = self.HTMLBOX.format(self.str_time_remaining()) def display(self): pass def done(self): if self.clear: self._box.close()
class Grid(object): ''' The class automatically closes Datagrid when reloaded and additionally display the Datagrid in a box. ''' def __init__(self): # Initialize the chart with default ticker self.data_grid = DataGrid(data=[], layout=Layout(display='none', flex='1')) self.box = HBox([self.data_grid]) def close(self): self.data_grid.close() self.box.close() def show(self): return self.box def populate_data(self, data): self.close() self.data_grid = DataGrid(data=data, layout=Layout(height='500px', flex='1')) self.box = HBox([self.data_grid])
class VerboseOptimization(object): def __init__(self, model, opt, maxiters, verbose=False, current_iteration=0, ipython_notebook=True, clear_after_finish=False): self.verbose = verbose if self.verbose: self.model = model self.iteration = current_iteration self.p_iter = self.iteration self.maxiters = maxiters self.len_maxiters = len(str(int(maxiters))) self.opt_name = opt.opt_name self.opt = opt self.model.add_observer(self, self.print_status) self.status = 'running' self.clear = clear_after_finish self.update() try: # pragma: no cover from IPython.display import display from ipywidgets import IntProgress, HTML, Box, VBox, HBox self.text = HTML(width='100%') self.progress = IntProgress(min=0, max=maxiters) #self.progresstext = Text(width='100%', disabled=True, value='0/{}'.format(maxiters)) self.model_show = HTML() self.ipython_notebook = ipython_notebook get_ipython except: # Not in Ipython notebook self.ipython_notebook = False if self.ipython_notebook: # pragma: no cover left_col = VBox( children=[self.progress, self.text], padding=2, width='40%') right_col = Box( children=[self.model_show], padding=2, width='60%') self.hor_align = HBox( children=[left_col, right_col], width='100%', orientation='horizontal') display(self.hor_align) try: self.text.set_css('width', '100%') left_col.set_css({ 'padding': '2px', 'width': "100%", }) right_col.set_css({ 'padding': '2px', }) self.hor_align.set_css({ 'width': "100%", }) self.hor_align.remove_class('vbox') self.hor_align.add_class('hbox') left_col.add_class("box-flex1") right_col.add_class('box-flex0') except: pass # self.text.add_class('box-flex2') # self.progress.add_class('box-flex1') else: self.exps = exponents(self.fnow, self.current_gradient) print('Running {} Code:'.format(self.opt_name)) print(' {3:7s} {0:{mi}s} {1:11s} {2:11s}'.format( "i", "f", "|g|", "runtime", mi=self.len_maxiters)) def __enter__(self): self.start = time.time() self._time = self.start return self def print_out(self, seconds): if seconds < 60: ms = (seconds % 1)*100 self.timestring = "{s:0>2d}s{ms:0>2d}".format( s=int(seconds), ms=int(ms)) else: m, s = divmod(seconds, 60) if m > 59: h, m = divmod(m, 60) if h > 23: d, h = divmod(h, 24) self.timestring = '{d:0>2d}d{h:0>2d}h{m:0>2d}'.format( m=int(m), h=int(h), d=int(d)) else: self.timestring = '{h:0>2d}h{m:0>2d}m{s:0>2d}'.format( m=int(m), s=int(s), h=int(h)) else: ms = (seconds % 1)*100 self.timestring = '{m:0>2d}m{s:0>2d}s{ms:0>2d}'.format( m=int(m), s=int(s), ms=int(ms)) if self.ipython_notebook: # pragma: no cover names_vals = [['optimizer', "{:s}".format(self.opt_name)], ['runtime', "{:>s}".format(self.timestring)], ['evaluation', "{:>0{l}}".format( self.iteration, l=self.len_maxiters)], ['objective', "{: > 12.3E}".format(self.fnow)], ['||gradient||', "{: >+12.3E}".format(float(self.current_gradient))], ['status', "{:s}".format(self.status)], ] #message = "Lik:{:5.3E} Grad:{:5.3E} Lik:{:5.3E} Len:{!s}".format(float(m.log_likelihood()), np.einsum('i,i->', grads, grads), float(m.likelihood.variance), " ".join(["{:3.2E}".format(l) for l in m.kern.lengthscale.values])) html_begin = """<style type="text/css"> .tg-opt {font-family:"Courier New", Courier, monospace !important;padding:2px 3px;word-break:normal;border-collapse:collapse;border-spacing:0;border-color:#DCDCDC;margin:0px auto;width:100%;} .tg-opt td{font-family:"Courier New", Courier, monospace !important;font-weight:bold;color:#444;background-color:#F7FDFA;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#DCDCDC;} .tg-opt th{font-family:"Courier New", Courier, monospace !important;font-weight:normal;color:#fff;background-color:#26ADE4;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#DCDCDC;} .tg-opt .tg-left{font-family:"Courier New", Courier, monospace !important;font-weight:normal;text-align:left;} .tg-opt .tg-right{font-family:"Courier New", Courier, monospace !important;font-weight:normal;text-align:right;} </style> <table class="tg-opt">""" html_end = "</table>" html_body = "" for name, val in names_vals: html_body += "<tr>" html_body += "<td class='tg-left'>{}</td>".format(name) html_body += "<td class='tg-right'>{}</td>".format(val) html_body += "</tr>" self.text.value = html_begin + html_body + html_end self.progress.value = (self.iteration+1) #self.progresstext.value = '0/{}'.format((self.iteration+1)) self.model_show.value = self.model._repr_html_() else: n_exps = exponents(self.fnow, self.current_gradient) if self.iteration - self.p_iter >= 20 * np.random.rand(): a = self.iteration >= self.p_iter * 2.78 b = np.any(n_exps < self.exps) if a or b: self.p_iter = self.iteration print('') if b: self.exps = n_exps print('\r', end=' ') print('{3:} {0:>0{mi}g} {1:> 12e} {2:> 12e}'.format(self.iteration, float(self.fnow), float(self.current_gradient), "{:>8s}".format( self.timestring), mi=self.len_maxiters), end=' ') # print 'Iteration:', iteration, ' Objective:', fnow, ' Scale:', beta, '\r', sys.stdout.flush() def print_status(self, me, which=None): self.update() t = time.time() seconds = t-self.start #sys.stdout.write(" "*len(self.message)) if t-self._time > 1. or seconds < .2: self.print_out(seconds) self._time = t self.iteration += 1 def update(self): self.fnow = self.model.objective_function() if self.model.obj_grads is not None: grad = self.model.obj_grads self.current_gradient = np.dot(grad, grad) else: self.current_gradient = np.nan def finish(self, opt): # pragma: no cover import warnings warnings.warn('Finish now automatic, deprecating', DeprecationWarning) def __exit__(self, type, value, traceback): if self.verbose: self.status = self.opt.status self.stop = time.time() self.model.remove_observer(self) self.print_out(self.stop - self.start) if not self.ipython_notebook: print() print('Runtime: {}'.format("{:>9s}".format(self.timestring))) print('Optimization status: {0}'.format(self.status)) print() elif self.clear: # pragma: no cover self.hor_align.close() else: # pragma: no cover if 'conv' in self.status.lower(): self.progress.bar_style = 'success' elif self.iteration >= self.maxiters: self.progress.bar_style = 'warning' else: self.progress.bar_style = 'danger'
class TileGridTool: """A tool for adding a dynamic Mercator tile grid to a map. The grid is recalculated/adapted dynamically to the visible part of the map only as the user zooms and pans over it. The grid level is limited from 0 to the current map zoom level plus 4, or there would be too many cells and the grid would be too dense to see anything else. """ def __init__( self, a_map: Map, description: str = "Mercator", position: str = "topright", ): """Instantiate a tile grid tool and place it on a map. """ self._max_zoom_delta = 4 self.tile_id = "" self.level = int(a_map.zoom) style = {"color": "#888888", "weight": 1, "fillOpacity": 0} hover_style = {"weight": 3, "fillOpacity": 0.1} self.gj = GeoJSON(data=geojson.Feature(), name=description, style=style, hover_style=hover_style) min, max = 0, int(a_map.zoom) + self._max_zoom_delta self.slider = IntSlider(description=description, min=min, max=max, value=self.level) self.ht = HTML(f"ID: {self.tile_id} Map zoom: {int(a_map.zoom)}") self.close_btn = Button( icon="times", button_style="info", tooltip="Close the widget", layout=Layout(width="32px"), ) self.widget = HBox([self.slider, self.ht, self.close_btn]) def hover(event, feature, **kwargs): if event == "mouseover": self.tile_id = feature["id"] self.ht.value = f"{self.tile_id} Map zoom: {int(a_map.zoom)}" def slider_moved(event): if event["type"] == "change" and event["name"] == "value": self.level = event["new"] # Ipyleaflet buglet(?): This name is updated in the GeoJSON layer, # but not in the LayersControl! self.gj.name = f"Mercator" # level {self.level}" self.tile_id = "" map_interacted({ "type": "change", "name": "bounds", "owner": a_map }) self.slider.observe(slider_moved) def map_interacted(event): if event["type"] == "change" and event["name"] == "bounds": self.ht.value = f"{self.tile_id}, Map zoom: {int(a_map.zoom)}" self.slider.max = int(a_map.zoom) + self._max_zoom_delta m = event["owner"] ((south, west), (north, east)) = m.bounds b_poly = list(m.bounds_polygon) b_poly += [tuple(b_poly[0])] # m += Polyline(locations=b_poly) # Attention in the order of west, south, east, north! tiles = mercantile.tiles(west, south, east, north, zooms=self.level) features = [mercantile.feature(t) for t in tiles] self.gj.data = geojson.FeatureCollection(features=features) # Ipyleaflet buglet(?): This name is updated in the GeoJSON layer, # but not in the LayersControl! self.gj.name = f"Mercator" # level {self.level}" self.gj.on_hover(hover) def close_click(change): self.widget.children = [] self.widget.close() self.close_btn.on_click(close_click) a_map += self.gj a_map.observe(map_interacted) map_interacted({"type": "change", "name": "bounds", "owner": a_map}) self.widget_control = WidgetControl(widget=self.widget, position=position) a_map.add_control(self.widget_control)