def test_antpath(): m = folium.Map([20., 0.], zoom_start=3) locations = [[59.355600, -31.99219], [55.178870, -42.89062], [47.754100, -43.94531], [38.272690, -37.96875], [27.059130, -41.13281], [16.299050, -36.56250], [8.4071700, -30.23437], [1.0546300, -22.50000], [-8.754790, -18.28125], [-21.61658, -20.03906], [-31.35364, -24.25781], [-39.90974, -30.93750], [-43.83453, -41.13281], [-47.75410, -49.92187], [-50.95843, -54.14062], [-55.97380, -56.60156]] antpath = plugins.AntPath(locations=locations) antpath.add_to(m) out = m._parent.render() # We verify that the script import is present. script = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet-ant-path.min.js"></script>' # noqa assert script in out # We verify that the script part is correct. tmpl = Template(""" {{this.get_name()}} = L.polyline.antPath( {{ this.locations|tojson }}, {{ this.options|tojson }} ) .addTo({{this._parent.get_name()}}); """) # noqa expected_rendered = tmpl.render(this=antpath) rendered = antpath._template.module.script(antpath) assert normalize(expected_rendered) == normalize(rendered)
def test_feature_group_sub_group(): m = folium.Map([0., 0.], zoom_start=6) fg = folium.FeatureGroup() m.add_child(fg) g1 = plugins.FeatureGroupSubGroup(fg, 'g1') m.add_child(g1) folium.Marker([1, 1]).add_to(g1) folium.Marker([-1, -1]).add_to(g1) g2 = plugins.FeatureGroupSubGroup(fg, 'g2') folium.Marker([-1, 1]).add_to(g2) folium.Marker([1, -1]).add_to(g2) m.add_child(g2) folium.LayerControl().add_to(m) out = normalize(m._parent.render()) # We verify that imports assert '<script src="https://unpkg.com/[email protected]/dist/leaflet.featuregroup.subgroup.js"></script>' in out # noqa # Verify the script part is okay. tmpl = Template(""" var {{ this.get_name() }} = L.featureGroup.subGroup( {{ this._group.get_name() }} ); {{ this.get_name() }}.addTo({{ this._parent.get_name() }}); """) assert normalize(tmpl.render(this=g1)) in out assert normalize(tmpl.render(this=g2)) in out
def test_image_overlay(): """Test image overlay.""" data = [[[1, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0]], [[1, 1, 0, 0.5], [0, 0, 1, 1], [0, 0, 1, 1]]] m = folium.Map() io = folium.raster_layers.ImageOverlay( data, [[0, -180], [90, 180]], mercator_project=True ) io.add_to(m) m._repr_html_() out = m._parent.render() # Verify the URL generation. url = ('data:image/png;base64,' 'iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAA' 'AF0lEQVR42mP4z8AARFDw/z/DeiA5H4QBV60H6ABl9ZIAAAAASUVORK5CYII=') assert io.url == url # Verify the script part is okay. tmpl = Template(""" var {{this.get_name()}} = L.imageOverlay( "{{ this.url }}", {{ this.bounds }}, {{ this.options }} ).addTo({{this._parent.get_name()}}); """) assert normalize(tmpl.render(this=io)) in normalize(out) bounds = m.get_bounds() assert bounds == [[0, -180], [90, 180]], bounds
def test_float_image(): m = folium.Map([45., 3.], zoom_start=4) url = 'https://raw.githubusercontent.com/SECOORA/static_assets/master/maps/img/rose.png' szt = plugins.FloatImage(url, bottom=60, left=70) m.add_child(szt) m._repr_html_() out = normalize(m._parent.render()) # Verify that the div has been created. tmpl = Template(""" <img id="{{this.get_name()}}" alt="float_image" src="https://raw.githubusercontent.com/SECOORA/static_assets/master/maps/img/rose.png" style="z-index: 999999"> </img> """) assert normalize(tmpl.render(this=szt)) in out # Verify that the style has been created. tmpl = Template(""" <style> #{{this.get_name()}} { position:absolute; bottom:60%; left:70%; } </style> """) assert normalize(tmpl.render(this=szt)) in out bounds = m.get_bounds() assert bounds == [[None, None], [None, None]], bounds
def test_feature_group_sub_group(): m = folium.Map([0., 0.], zoom_start=6) fg = folium.FeatureGroup() m.add_child(fg) g1 = plugins.FeatureGroupSubGroup(fg, 'g1') m.add_child(g1) folium.Marker([1, 1]).add_to(g1) folium.Marker([-1, -1]).add_to(g1) g2 = plugins.FeatureGroupSubGroup(fg, 'g2') folium.Marker([-1, 1]).add_to(g2) folium.Marker([1, -1]).add_to(g2) m.add_child(g2) folium.LayerControl().add_to(m) out = normalize(m._parent.render()) # We verify that imports assert '<script src="https://unpkg.com/[email protected]/dist/leaflet.featuregroup.subgroup.js"></script>' in out # noqa # Verify the script part is okay. tmpl = Template(""" var {{ this.get_name() }} = L.featureGroup.subGroup( {{ this._group.get_name() }} ); {{ this.get_name() }}.addTo({{ this._parent.get_name() }}); """) assert normalize(tmpl.render(this=g1)) in out assert normalize(tmpl.render(this=g2)) in out
def test_image_overlay(): """Test image overlay.""" data = [[[1, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0]], [[1, 1, 0, 0.5], [0, 0, 1, 1], [0, 0, 1, 1]]] m = folium.Map() io = folium.raster_layers.ImageOverlay(data, [[0, -180], [90, 180]], mercator_project=True) io.add_to(m) m._repr_html_() out = m._parent.render() # Verify the URL generation. url = ('data:image/png;base64,' 'iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAA' 'AF0lEQVR42mP4z8AARFDw/z/DeiA5H4QBV60H6ABl9ZIAAAAASUVORK5CYII=') assert io.url == url # Verify the script part is okay. tmpl = Template(""" var {{this.get_name()}} = L.imageOverlay( "{{ this.url }}", {{ this.bounds }}, {{ this.options }} ).addTo({{this._parent.get_name()}}); """) assert normalize(tmpl.render(this=io)) in normalize(out) bounds = m.get_bounds() assert bounds == [[0, -180], [90, 180]], bounds
def test_mulyipolyline(): m = Map() locations = [[[45.51, -122.68], [37.77, -122.43], [34.04, -118.2]], [[40.78, -73.91], [41.83, -87.62], [32.76, -96.72]]] multipolyline = PolyLine(locations=locations, popup='MultiPolyLine') multipolyline.add_to(m) expected_options = { 'smoothFactor': 1.0, 'noClip': False, 'bubblingMouseEvents': True, 'color': '#3388ff', 'dashArray': None, 'dashOffset': None, 'fill': False, 'fillColor': '#3388ff', 'fillOpacity': 0.2, 'fillRule': 'evenodd', 'lineCap': 'round', 'lineJoin': 'round', 'opacity': 1.0, 'stroke': True, 'weight': 3, } m._repr_html_() expected_rendered = """ var {name} = L.polyline( {locations}, {{ "bubblingMouseEvents": true, "color": "#3388ff", "dashArray": null, "dashOffset": null, "fill": false, "fillColor": "#3388ff", "fillOpacity": 0.2, "fillRule": "evenodd", "lineCap": "round", "lineJoin": "round", "noClip": false, "opacity": 1.0, "smoothFactor": 1.0, "stroke": true, "weight": 3 }} ) .addTo({map}); """.format(locations=locations, name=multipolyline.get_name(), map=m.get_name()) rendered = multipolyline._template.module.script(multipolyline) assert normalize(rendered) == normalize(expected_rendered) assert multipolyline.get_bounds() == get_bounds(locations) assert json.dumps(multipolyline.to_dict()) == multipolyline.to_json() assert multipolyline.options == expected_options
def test_mulyipolyline(): m = Map() locations = [[[45.51, -122.68], [37.77, -122.43], [34.04, -118.2]], [[40.78, -73.91], [41.83, -87.62], [32.76, -96.72]]] multipolyline = PolyLine(locations=locations, popup='MultiPolyLine') multipolyline.add_to(m) expected_options = { 'smoothFactor': 1.0, 'noClip': False, 'bubblingMouseEvents': True, 'color': '#3388ff', 'dashArray': None, 'dashOffset': None, 'fill': False, 'fillColor': '#3388ff', 'fillOpacity': 0.2, 'fillRule': 'evenodd', 'lineCap': 'round', 'lineJoin': 'round', 'opacity': 1.0, 'stroke': True, 'weight': 3, } m._repr_html_() expected_rendered = """ var {name} = L.polyline( {locations}, {{ "bubblingMouseEvents": true, "color": "#3388ff", "dashArray": null, "dashOffset": null, "fill": false, "fillColor": "#3388ff", "fillOpacity": 0.2, "fillRule": "evenodd", "lineCap": "round", "lineJoin": "round", "noClip": false, "opacity": 1.0, "smoothFactor": 1.0, "stroke": true, "weight": 3 }} ) .addTo({map}); """.format(locations=locations, name=multipolyline.get_name(), map=m.get_name()) rendered = multipolyline._template.module.script(multipolyline) assert normalize(rendered) == normalize(expected_rendered) assert multipolyline.get_bounds() == get_bounds(locations) assert json.dumps(multipolyline.to_dict()) == multipolyline.to_json() assert multipolyline.options == expected_options
def test_polygon_marker(): m = Map() locations = [[35.6636, 139.7634], [35.6629, 139.7664], [35.6663, 139.7706], [35.6725, 139.7632], [35.6728, 139.7627], [35.6720, 139.7606], [35.6682, 139.7588], [35.6663, 139.7627]] polygon = Polygon(locations=locations, popup='I am a polygon') polygon.add_to(m) expected_options = { 'bubblingMouseEvents': True, 'color': '#3388ff', 'dashArray': None, 'dashOffset': None, 'fill': False, 'fillColor': '#3388ff', 'fillOpacity': 0.2, 'fillRule': 'evenodd', 'lineCap': 'round', 'lineJoin': 'round', 'noClip': False, 'opacity': 1.0, 'smoothFactor': 1.0, 'stroke': True, 'weight': 3, } m._repr_html_() expected_rendered = """ var {name} = L.polygon( {locations}, {{ "bubblingMouseEvents": true, "color": "#3388ff", "dashArray": null, "dashOffset": null, "fill": false, "fillColor": "#3388ff", "fillOpacity": 0.2, "fillRule": "evenodd", "lineCap": "round", "lineJoin": "round", "noClip": false, "opacity": 1.0, "smoothFactor": 1.0, "stroke": true, "weight": 3 }} ) .addTo({map}); """.format(locations=locations, name=polygon.get_name(), map=m.get_name()) rendered = polygon._template.module.script(polygon) assert normalize(rendered) == normalize(expected_rendered) assert polygon.get_bounds() == get_bounds(locations) assert json.dumps(polygon.to_dict()) == polygon.to_json() assert polygon.options == expected_options
def test_scroll_zoom_toggler(): m = folium.Map([45., 3.], zoom_start=4) szt = plugins.ScrollZoomToggler() m.add_child(szt) out = normalize(m._parent.render()) # Verify that the div has been created. tmpl = Template(""" <img id="{{this.get_name()}}" alt="scroll" src="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/png/512/arrow-move.png" style="z-index: 999999" onclick="{{this._parent.get_name()}}.toggleScroll()"></img> """) assert ''.join(tmpl.render(this=szt).split()) in ''.join(out.split()) # Verify that the style has been created tmpl = Template(""" <style> #{{this.get_name()}} { position:absolute; width:35px; bottom:10px; height:35px; left:10px; background-color:#fff; text-align:center; line-height:35px; vertical-align: middle; } </style> """) expected = normalize(tmpl.render(this=szt)) assert expected in out # Verify that the script is okay. tmpl = Template(""" {{this._parent.get_name()}}.scrollEnabled = true; {{this._parent.get_name()}}.toggleScroll = function() { if (this.scrollEnabled) { this.scrollEnabled = false; this.scrollWheelZoom.disable(); } else { this.scrollEnabled = true; this.scrollWheelZoom.enable(); } }; {{this._parent.get_name()}}.toggleScroll(); """) expected = normalize(tmpl.render(this=szt)) assert expected in out bounds = m.get_bounds() assert bounds == [[None, None], [None, None]], bounds
def test_custom_pane_show(): m = Map() pane = CustomPane('test-name', z_index=625, pointer_events=False).add_to(m) rendered = pane._template.module.script(this=pane, kwargs={}) expected = """ var {pane_name} = {map_name}.createPane("test-name"); {pane_name}.style.zIndex = 625; {pane_name}.style.pointerEvents = 'none'; """.format(pane_name=pane.get_name(), map_name=m.get_name()) assert normalize(rendered) == normalize(expected)
def test_semicircle(): m = folium.Map([30., 0.], zoom_start=3) sc1 = plugins.SemiCircle( (34, -43), radius=400000, arc=300, direction=20, color='red', fill_color='red', opacity=0, popup='Direction - 20 degrees, arc 300 degrees' ) sc2 = plugins.SemiCircle( (46, -30), radius=400000, start_angle=10, stop_angle=50, color='red', fill_color='red', opacity=0, popup='Start angle - 10 degrees, Stop angle - 50 degrees' ) m.add_child(sc1) m.add_child(sc2) m._repr_html_() out = normalize(m._parent.render()) # We verify that the script import is present. script = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/Semicircle.min.js"></script>' # noqa assert script in out # We verify that the script part is correct. tmpl_sc1 = Template(u""" var {{ this.get_name() }} = L.semiCircle( {{ this.location|tojson }}, {{ this.options | tojson }} ) .setDirection{{ this.direction }} .addTo({{ this._parent.get_name() }}); """) tmpl_sc2 = Template(u""" var {{ this.get_name() }} = L.semiCircle( {{ this.location|tojson }}, {{ this.options | tojson }} ) .addTo({{ this._parent.get_name() }}); """) assert normalize(tmpl_sc1.render(this=sc1)) in out assert normalize(tmpl_sc2.render(this=sc2)) in out bounds = m.get_bounds() assert bounds == [[34, -43], [46, -30]], bounds
def test_polyline(): m = Map() locations = [[40.0, -80.0], [45.0, -80.0]] polyline = PolyLine(locations=locations, popup='I am PolyLine') polyline.add_to(m) expected_options = { 'smoothFactor': 1.0, 'noClip': False, 'bubblingMouseEvents': True, 'color': '#3388ff', 'dashArray': None, 'dashOffset': None, 'fill': False, 'fillColor': '#3388ff', 'fillOpacity': 0.2, 'fillRule': 'evenodd', 'lineCap': 'round', 'lineJoin': 'round', 'opacity': 1.0, 'stroke': True, 'weight': 3, } m._repr_html_() expected_rendered = """ var {name} = L.polyline( {locations}, {{ "bubblingMouseEvents": true, "color": "#3388ff", "dashArray": null, "dashOffset": null, "fill": false, "fillColor": "#3388ff", "fillOpacity": 0.2, "fillRule": "evenodd", "lineCap": "round", "lineJoin": "round", "noClip": false, "opacity": 1.0, "smoothFactor": 1.0, "stroke": true, "weight": 3 }} ) .addTo({map}); """.format(locations=locations, name=polyline.get_name(), map=m.get_name()) rendered = polyline._template.module.script(polyline) assert normalize(rendered) == normalize(expected_rendered) assert polyline.get_bounds() == get_bounds(locations) assert json.dumps(polyline.to_dict()) == polyline.to_json() assert polyline.options == expected_options
def test_terminator(): m = folium.Map([45., 3.], zoom_start=1) t = plugins.Terminator().add_to(m) out = normalize(m._parent.render()) # Verify that the script is okay. tmpl = Template('L.terminator().addTo({{this._parent.get_name()}});') expected = normalize(tmpl.render(this=t)) assert expected in out bounds = m.get_bounds() assert bounds == [[None, None], [None, None]], bounds
def test_vectorgrid(): m = folium.Map(location=(30, 20), zoom_start=4) url = "https://free-{s}.tilehosting.com/data/v3/{z}/{x}/{y}.pbf?token={token}" vc = VectorGridProtobuf(url, "test").add_to(m) out = normalize(m._parent.render()) expected = normalize(VectorGridProtobuf._template.render(this=vc)) assert expected in out script = f'<script src="{VectorGridProtobuf.default_js[0][1]}"></script>' assert script in out assert url in out assert "L.vectorGrid.protobuf" in out
def test_terminator(): m = folium.Map([45., 3.], zoom_start=1) t = plugins.Terminator().add_to(m) out = normalize(m._parent.render()) # Verify that the script is okay. tmpl = Template('L.terminator().addTo({{this._parent.get_name()}});') expected = normalize(tmpl.render(this=t)) assert expected in out bounds = m.get_bounds() assert bounds == [[None, None], [None, None]], bounds
def test_fullscreen(): m = folium.Map([47, 3], zoom_start=1) fs = plugins.Fullscreen().add_to(m) out = normalize(m._parent.render()) # verify that the fullscreen control was rendered tmpl = Template(""" L.control.fullscreen( {{ this.options|tojson }} ).addTo({{this._parent.get_name()}}); """) assert normalize(tmpl.render(this=fs)) in out
def test_fullscreen(): m = folium.Map([47, 3], zoom_start=1) fs = plugins.Fullscreen().add_to(m) out = normalize(m._parent.render()) # verify that the fullscreen control was rendered tmpl = Template(""" L.control.fullscreen( {{ this.options|tojson }} ).addTo({{this._parent.get_name()}}); """) assert normalize(tmpl.render(this=fs)) in out
def test_popup_sticky(): m = Map() popup = Popup('Some text.', sticky=True).add_to(m) rendered = popup._template.render(this=popup, kwargs={}) expected = """ var {popup_name} = L.popup({{ "autoClose": false, "closeOnClick": false, "maxWidth": "100%" }}); var {html_name} = $(`<div id="{html_name}" style="width: 100.0%; height: 100.0%;">Some text.</div>`)[0]; {popup_name}.setContent({html_name}); {map_name}.bindPopup({popup_name}); """.format(popup_name=popup.get_name(), html_name=list(popup.html._children.keys())[0], map_name=m.get_name()) assert normalize(rendered) == normalize(expected)
def test_heat_map(): np.random.seed(3141592) data = (np.random.normal(size=(100, 2)) * np.array([[1, 1]]) + np.array([[48, 5]])) m = folium.Map([48., 5.], tiles='stamentoner', zoom_start=6) hm = HeatMap(data) m.add_child(hm) m._repr_html_() out = normalize(m._parent.render()) # We verify that the script import is present. script = '<script src="https://leaflet.github.io/Leaflet.heat/dist/leaflet-heat.js"></script>' # noqa assert script in out # We verify that the script part is correct. tmpl = Template(""" var {{this.get_name()}} = L.heatLayer( {{this.data}}, { minOpacity: {{this.min_opacity}}, maxZoom: {{this.max_zoom}}, max: {{this.max_val}}, radius: {{this.radius}}, blur: {{this.blur}}, gradient: {{this.gradient}} }) .addTo({{this._parent.get_name()}}); """) assert tmpl.render(this=hm) bounds = m.get_bounds() assert bounds == [[46.218566840847025, 3.0302801394447734], [50.75345011431167, 7.132453997672826]], bounds
def test_pattern(): m = folium.Map([40., -105.], zoom_start=6) stripes = plugins.pattern.StripePattern(angle=-45) stripes.add_to(m) circles = plugins.pattern.CirclePattern(width=20, height=20, radius=5, fill_opacity=0.5, opacity=1) def style_function(feature): default_style = { 'opacity': 1.0, 'fillColor': '#ffff00', 'color': 'black', 'weight': 2 } if feature['properties']['name'] == 'Colorado': default_style['fillPattern'] = stripes default_style['fillOpacity'] = 1.0 if feature['properties']['name'] == 'Utah': default_style['fillPattern'] = circles default_style['fillOpacity'] = 1.0 return default_style data = os.path.join(os.path.dirname(__file__), os.pardir, 'us-states.json') folium.GeoJson(data, style_function=style_function).add_to(m) out = normalize(m._parent.render()) # We verify that the script import is present. script = '<script src="https://teastman.github.io/Leaflet.pattern/leaflet.pattern.js"></script>' # noqa assert script in out
def test_pattern(): m = folium.Map([40., -105.], zoom_start=6) stripes = plugins.pattern.StripePattern(angle=-45) stripes.add_to(m) circles = plugins.pattern.CirclePattern(width=20, height=20, radius=5, fill_opacity=0.5, opacity=1) def style_function(feature): default_style = { 'opacity': 1.0, 'fillColor': '#ffff00', 'color': 'black', 'weight': 2 } if feature['properties']['name'] == 'Colorado': default_style['fillPattern'] = stripes default_style['fillOpacity'] = 1.0 if feature['properties']['name'] == 'Utah': default_style['fillPattern'] = circles default_style['fillOpacity'] = 1.0 return default_style data = os.path.join(os.path.dirname(__file__), os.pardir, 'us-states.json') folium.GeoJson(data, style_function=style_function).add_to(m) out = normalize(m._parent.render()) # We verify that the script import is present. script = '<script src="https://teastman.github.io/Leaflet.pattern/leaflet.pattern.js"></script>' # noqa assert script in out
def test_heat_map(): np.random.seed(3141592) data = (np.random.normal(size=(100, 2)) * np.array([[1, 1]]) + np.array([[48, 5]])) m = folium.Map([48., 5.], tiles='stamentoner', zoom_start=6) hm = HeatMap(data) m.add_child(hm) m._repr_html_() out = normalize(m._parent.render()) # We verify that the script import is present. script = '<script src="https://leaflet.github.io/Leaflet.heat/dist/leaflet-heat.js"></script>' # noqa assert script in out # We verify that the script part is correct. tmpl = Template(""" var {{this.get_name()}} = L.heatLayer( {{this.data}}, { minOpacity: {{this.min_opacity}}, maxZoom: {{this.max_zoom}}, max: {{this.max_val}}, radius: {{this.radius}}, blur: {{this.blur}}, gradient: {{this.gradient}} }) .addTo({{this._parent.get_name()}}); """) assert tmpl.render(this=hm) bounds = m.get_bounds() assert bounds == [[46.218566840847025, 3.0302801394447734], [50.75345011431167, 7.132453997672826]], bounds
def test_polyline_text_path(): m = folium.Map([20., 0.], zoom_start=3) wind_locations = [[59.355600, -31.99219], [55.178870, -42.89062], [47.754100, -43.94531], [38.272690, -37.96875], [27.059130, -41.13281], [16.299050, -36.56250], [8.4071700, -30.23437], [1.0546300, -22.50000], [-8.754790, -18.28125], [-21.61658, -20.03906], [-31.35364, -24.25781], [-39.90974, -30.93750], [-43.83453, -41.13281], [-47.75410, -49.92187], [-50.95843, -54.14062], [-55.97380, -56.60156]] wind_line = folium.PolyLine(wind_locations, weight=15, color='#8EE9FF') attr = {'fill': '#007DEF', 'font-weight': 'bold', 'font-size': '24'} wind_textpath = plugins.PolyLineTextPath(wind_line, ') ', repeat=True, offset=7, attributes=attr) m.add_child(wind_line) m.add_child(wind_textpath) out = normalize(m._parent.render()) # We verify that the script import is present. script = '<script src="https://rawcdn.githack.com/makinacorpus/Leaflet.TextPath/leaflet0.8-dev/leaflet.textpath.js"></script>' # noqa assert script in out # We verify that the script part is correct. tmpl = Template(""" {{ this.polyline.get_name() }}.setText( "{{this.text}}", {{ this.options|tojson }} ); """) expected = normalize(tmpl.render(this=wind_textpath)) assert expected in out
def test_boat_marker_with_no_wind_speed_or_heading(): m = folium.Map([30., 0.], zoom_start=3) bm1 = plugins.BoatMarker((34, -43), heading=45, color='#8f8') m.add_child(bm1) out = normalize(m._parent.render()) # We verify that the script part is correct. tmpl = Template(""" var {{ this.get_name() }} = L.boatMarker( {{ this.location|tojson }}, {{ this.options|tojson }} ).addTo({{ this._parent.get_name() }}); {{ this.get_name() }}.setHeading({{ this.heading }}); """) assert normalize(tmpl.render(this=bm1)) in out
def test_polylineoffset_without_offset(): m = folium.Map([20.0, 0.0], zoom_start=3) locations = [[59.355600, -31.99219], [55.178870, -42.89062]] polylineoffset = plugins.PolyLineOffset(locations=locations) polylineoffset.add_to(m) m._repr_html_() out = m._parent.render() # We verify that the script import is present. script = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/leaflet.polylineoffset.min.js"></script>' # noqa assert script in out # We verify that the script part is correct. expected_rendered = """ var {name} = L.polyline( {locations}, {{ "bubblingMouseEvents": true, "color": "#3388ff", "dashArray": null, "dashOffset": null, "fill": false, "fillColor": "#3388ff", "fillOpacity": 0.2, "fillRule": "evenodd", "lineCap": "round", "lineJoin": "round", "noClip": false, "offset": 0, "opacity": 1.0, "smoothFactor": 1.0, "stroke": true, "weight": 3 }} ) .addTo({map}); """.format(locations=locations, name=polylineoffset.get_name(), map=m.get_name()) rendered = polylineoffset._template.module.script(polylineoffset) assert normalize(expected_rendered) == normalize(rendered)
def test_polylineoffset_without_offset(): m = folium.Map([20.0, 0.0], zoom_start=3) locations = [[59.355600, -31.99219], [55.178870, -42.89062]] polylineoffset = plugins.PolyLineOffset(locations=locations) polylineoffset.add_to(m) m._repr_html_() out = m._parent.render() # We verify that the script import is present. script = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/leaflet.polylineoffset.min.js"></script>' # noqa assert script in out # We verify that the script part is correct. expected_rendered = """ var {name} = L.polyline( {locations}, {{ "bubblingMouseEvents": true, "color": "#3388ff", "dashArray": null, "dashOffset": null, "fill": false, "fillColor": "#3388ff", "fillOpacity": 0.2, "fillRule": "evenodd", "lineCap": "round", "lineJoin": "round", "noClip": false, "offset": 0, "opacity": 1.0, "smoothFactor": 1.0, "stroke": true, "weight": 3 }} ) .addTo({map}); """.format( locations=locations, name=polylineoffset.get_name(), map=m.get_name() ) rendered = polylineoffset._template.module.script(polylineoffset) assert normalize(expected_rendered) == normalize(rendered)
def test_minimap(): m = folium.Map(location=(30, 20), zoom_start=4) minimap = plugins.MiniMap() m.add_child(minimap) out = normalize(m._parent.render()) # Verify that a new minimap is getting created. assert 'new L.Control.MiniMap' in out m = folium.Map(location=(30, 20), zoom_start=4) minimap = plugins.MiniMap(tile_layer="Stamen Toner") minimap.add_to(m) out = normalize(m._parent.render()) # verify that Stamen Toner tiles are being used assert 'https://stamen-tiles' in out
def test_minimap(): m = folium.Map(location=(30, 20), zoom_start=4) minimap = plugins.MiniMap() m.add_child(minimap) out = normalize(m._parent.render()) # Verify that a new minimap is getting created. assert 'new L.Control.MiniMap' in out m = folium.Map(location=(30, 20), zoom_start=4) minimap = plugins.MiniMap(tile_layer="Stamen Toner") minimap.add_to(m) out = normalize(m._parent.render()) # verify that Stamen Toner tiles are being used assert 'https://stamen-tiles' in out
def test_beautify_icon(): m = folium.Map([30., 0.], zoom_start=3) # BeautifyIcons ic1 = plugins.BeautifyIcon( icon='plane', border_color='#b3334f', text_color='#b3334f') ic2 = plugins.BeautifyIcon(border_color='#00ABDC', text_color='#00ABDC', number=10, inner_icon_style='margin-top:0;') # Markers, add icons as keyword argument bm1 = folium.Marker(location=[46, -122], popup='Portland, OR', icon=ic1 ).add_to(m) bm2 = folium.Marker( location=[50, -121], icon=ic2 ).add_to(m) m.add_child(bm1) m.add_child(bm2) m._repr_html_() out = normalize(m._parent.render()) # We verify that the script import is present. script = '<script src="https://rawcdn.githack.com/marslan390/BeautifyMarker/master/leaflet-beautify-marker-icon.js"></script>' # noqa assert script in out # We verify that the css import is present. css = '<link rel="stylesheet" href="https://rawcdn.githack.com/marslan390/BeautifyMarker/master/leaflet-beautify-marker-icon.css"/>' # noqa assert css in out # We verify that the Beautiful Icons are rendered correctly. tmpl = Template(u""" var {{this.get_name()}} = new L.BeautifyIcon.icon({{ this.options|tojson }}) {{this._parent.get_name()}}.setIcon({{this.get_name()}}); """) # noqa assert normalize(tmpl.render(this=ic1)) in out assert normalize(tmpl.render(this=ic2)) in out
def test_boat_marker(): m = folium.Map([30., 0.], zoom_start=3) bm1 = plugins.BoatMarker( (34, -43), heading=45, wind_heading=150, wind_speed=45, color='#8f8') bm2 = plugins.BoatMarker( (46, -30), heading=-20, wind_heading=46, wind_speed=25, color='#88f') m.add_child(bm1) m.add_child(bm2) m._repr_html_() out = normalize(m._parent.render()) # We verify that the script import is present. script = '<script src="https://unpkg.com/leaflet.boatmarker/leaflet.boatmarker.min.js"></script>' # noqa assert script in out # We verify that the script part is correct. tmpl = Template(u""" var {{ this.get_name() }} = L.boatMarker( {{ this.location|tojson }}, {{ this.options|tojson }} ).addTo({{ this._parent.get_name() }}); {{ this.get_name() }}.setHeadingWind( {{ this.heading }}, {{ this.wind_speed }}, {{ this.wind_heading }} ); """) assert normalize(tmpl.render(this=bm1)) in out assert normalize(tmpl.render(this=bm2)) in out bounds = m.get_bounds() assert bounds == [[34, -43], [46, -30]], bounds
def test_marker_cluster(): N = 100 np.random.seed(seed=26082009) data = np.array([ np.random.uniform(low=35, high=60, size=N), # Random latitudes. np.random.uniform(low=-12, high=30, size=N), # Random longitudes. ]).T m = folium.Map([45., 3.], zoom_start=4) mc = plugins.MarkerCluster(data).add_to(m) out = normalize(m._parent.render()) # We verify that imports assert '<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/leaflet.markercluster.js"></script>' in out # noqa assert '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/MarkerCluster.css"/>' in out # noqa assert '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/MarkerCluster.Default.css"/>' in out # noqa # Verify the script part is okay. tmpl = Template(""" var {{this.get_name()}} = L.markerClusterGroup( {{ this.options|tojson }} ); {%- if this.icon_create_function is not none %} {{ this.get_name() }}.options.iconCreateFunction = {{ this.icon_create_function.strip() }}; {%- endif %} {{this._parent.get_name()}}.addLayer({{this.get_name()}}); {% for marker in this._children.values() %} var {{marker.get_name()}} = L.marker( {{ marker.location|tojson }}, {} ).addTo({{this.get_name()}}); {% endfor %} """) expected = normalize(tmpl.render(this=mc)) assert expected in out bounds = m.get_bounds() np.testing.assert_allclose(bounds, [[35.147332572663785, -11.520684337300109], [59.839718052359274, 29.94931046497927]])
def test_map_build(self): """Test map build.""" # Standard map. self.setup() rendered = self.m._parent.render() html_templ = self.env.get_template('fol_template.html') attr = 'http://openstreetmap.org' tile_layers = [{ 'id': 'tile_layer_' + '0' * 32, 'address': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', 'attr': attr, 'max_native_zoom': 20, 'max_zoom': 20, 'min_zoom': 0, 'detect_retina': False, 'no_wrap': False, 'tms': False, 'opacity': 1, 'subdomains': 'abc' }] tmpl = { 'map_id': 'map_' + '0' * 32, 'lat': 45.5236, 'lon': -122.675, 'width': 'width: 900.0px;', 'height': 'height: 400.0px;', 'zoom_level': 4, 'max_bounds': True, 'min_lat': -90, 'max_lat': 90, 'min_lon': -180, 'max_lon': 180, 'tile_layers': tile_layers, 'crs': 'EPSG3857', 'world_copy_jump': False, 'zoom_control': True } expected = html_templ.render(tmpl, plugins={}) assert normalize(rendered) == normalize(expected)
def test_dual_map(): m = folium.plugins.DualMap((0, 0)) folium.FeatureGroup(name='both').add_to(m) folium.FeatureGroup(name='left').add_to(m.m1) folium.FeatureGroup(name='right').add_to(m.m2) figure = m.get_root() assert isinstance(figure, folium.Figure) out = normalize(figure.render()) script = '<script src="https://rawcdn.githack.com/jieter/Leaflet.Sync/master/L.Map.Sync.js"></script>' # noqa assert script in out tmpl = Template(""" {{ this.m1.get_name() }}.sync({{ this.m2.get_name() }}); {{ this.m2.get_name() }}.sync({{ this.m1.get_name() }}); """) assert normalize(tmpl.render(this=m)) in out
def test_dual_map(): m = folium.plugins.DualMap((0, 0)) folium.FeatureGroup(name='both').add_to(m) folium.FeatureGroup(name='left').add_to(m.m1) folium.FeatureGroup(name='right').add_to(m.m2) figure = m.get_root() assert isinstance(figure, folium.Figure) out = normalize(figure.render()) script = '<script src="https://cdn.jsdelivr.net/gh/jieter/Leaflet.Sync/L.Map.Sync.min.js"></script>' # noqa assert script in out tmpl = Template(""" {{ this.m1.get_name() }}.sync({{ this.m2.get_name() }}); {{ this.m2.get_name() }}.sync({{ this.m1.get_name() }}); """) assert normalize(tmpl.render(this=m)) in out
def test_boat_marker_with_no_wind_speed_or_heading(): m = folium.Map([30., 0.], zoom_start=3) bm1 = plugins.BoatMarker( (34, -43), heading=45, color='#8f8') m.add_child(bm1) out = normalize(m._parent.render()) # We verify that the script part is correct. tmpl = Template(""" var {{ this.get_name() }} = L.boatMarker( {{ this.location|tojson }}, {{ this.options|tojson }} ).addTo({{ this._parent.get_name() }}); {{ this.get_name() }}.setHeading({{ this.heading }}); """) assert normalize(tmpl.render(this=bm1)) in out
def test_fast_marker_cluster(): n = 100 np.random.seed(seed=26082009) data = np.array([ np.random.uniform(low=35, high=60, size=n), np.random.uniform(low=-12, high=30, size=n), ]).T m = folium.Map([45., 3.], zoom_start=4) mc = FastMarkerCluster(data).add_to(m) out = normalize(m._parent.render()) # We verify that imports assert '<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/leaflet.markercluster.js"></script>' in out # noqa assert '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/MarkerCluster.css"/>' in out # noqa assert '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/MarkerCluster.Default.css"/>' in out # noqa # Verify the script part is okay. tmpl = Template(""" var {{ this.get_name() }} = (function(){ {{ this.callback }} var data = {{ this.data|tojson }}; var cluster = L.markerClusterGroup({{ this.options|tojson }}); {%- if this.icon_create_function is not none %} cluster.options.iconCreateFunction = {{ this.icon_create_function.strip() }}; {%- endif %} for (var i = 0; i < data.length; i++) { var row = data[i]; var marker = callback(row); marker.addTo(cluster); } cluster.addTo({{ this._parent.get_name() }}); return cluster; })(); """) expected = normalize(tmpl.render(this=mc)) assert expected in out
def test_fast_marker_cluster(): n = 100 np.random.seed(seed=26082009) data = np.array([ np.random.uniform(low=35, high=60, size=n), # Random latitudes. np.random.uniform(low=-12, high=30, size=n), # Random longitudes. range(n), # Popups. ]).tolist() m = folium.Map([45., 3.], zoom_start=4) mc = plugins.FastMarkerCluster(data, callback=None) m.add_child(mc) m._repr_html_() out = normalize(m._parent.render()) # We verify that imports assert '<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/leaflet.markercluster.js"></script>' in out # noqa assert '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/MarkerCluster.css"/>' in out # noqa assert '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/MarkerCluster.Default.css"/>' in out # noqa # Verify the script part is okay. tmpl = Template(""" {% macro script(this, kwargs) %} (function() { var data = {{this._data}}; var map = {{this._parent.get_name()}}; var cluster = L.markerClusterGroup(); {{this._callback}} for (var i = 0; i < data.length; i++) { var row = data[i]; var marker = callback(row, popup='names'); marker.addTo(cluster); } cluster.addTo(map); })(); {% endmacro %} """) assert normalize(tmpl.render(this=mc)) in out
def test_fast_marker_cluster(): n = 100 np.random.seed(seed=26082009) data = np.array([ np.random.uniform(low=35, high=60, size=n), np.random.uniform(low=-12, high=30, size=n), ]).T m = folium.Map([45., 3.], zoom_start=4) mc = FastMarkerCluster(data).add_to(m) out = normalize(m._parent.render()) # We verify that imports assert '<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/leaflet.markercluster.js"></script>' in out # noqa assert '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/MarkerCluster.css"/>' in out # noqa assert '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.1.0/MarkerCluster.Default.css"/>' in out # noqa # Verify the script part is okay. tmpl = Template(""" var {{ this.get_name() }} = (function(){ {{ this.callback }} var data = {{ this.data|tojson }}; var cluster = L.markerClusterGroup({{ this.options|tojson }}); {%- if this.icon_create_function is not none %} cluster.options.iconCreateFunction = {{ this.icon_create_function.strip() }}; {%- endif %} for (var i = 0; i < data.length; i++) { var row = data[i]; var marker = callback(row); marker.addTo(cluster); } cluster.addTo({{ this._parent.get_name() }}); return cluster; })(); """) expected = normalize(tmpl.render(this=mc)) assert expected in out
def test_boat_marker(): m = folium.Map([30., 0.], zoom_start=3) bm1 = plugins.BoatMarker((34, -43), heading=45, wind_heading=150, wind_speed=45, color='#8f8') bm2 = plugins.BoatMarker((46, -30), heading=-20, wind_heading=46, wind_speed=25, color='#88f') m.add_child(bm1) m.add_child(bm2) m._repr_html_() out = normalize(m._parent.render()) # We verify that the script import is present. script = '<script src="https://unpkg.com/leaflet.boatmarker/leaflet.boatmarker.min.js"></script>' # noqa assert script in out # We verify that the script part is correct. tmpl = Template(u""" var {{ this.get_name() }} = L.boatMarker( {{ this.location|tojson }}, {{ this.options|tojson }} ).addTo({{ this._parent.get_name() }}); {{ this.get_name() }}.setHeadingWind( {{ this.heading }}, {{ this.wind_speed }}, {{ this.wind_heading }} ); """) assert normalize(tmpl.render(this=bm1)) in out assert normalize(tmpl.render(this=bm2)) in out bounds = m.get_bounds() assert bounds == [[34, -43], [46, -30]], bounds
def test_polyline_text_path(): m = folium.Map([20., 0.], zoom_start=3) wind_locations = [[59.355600, -31.99219], [55.178870, -42.89062], [47.754100, -43.94531], [38.272690, -37.96875], [27.059130, -41.13281], [16.299050, -36.56250], [8.4071700, -30.23437], [1.0546300, -22.50000], [-8.754790, -18.28125], [-21.61658, -20.03906], [-31.35364, -24.25781], [-39.90974, -30.93750], [-43.83453, -41.13281], [-47.75410, -49.92187], [-50.95843, -54.14062], [-55.97380, -56.60156]] wind_line = folium.PolyLine(wind_locations, weight=15, color='#8EE9FF') attr = {'fill': '#007DEF', 'font-weight': 'bold', 'font-size': '24'} wind_textpath = plugins.PolyLineTextPath(wind_line, ') ', repeat=True, offset=7, attributes=attr) m.add_child(wind_line) m.add_child(wind_textpath) out = normalize(m._parent.render()) # We verify that the script import is present. script = '<script src="https://rawcdn.githack.com/makinacorpus/Leaflet.TextPath/leaflet0.8-dev/leaflet.textpath.js"></script>' # noqa assert script in out # We verify that the script part is correct. tmpl = Template(""" {{ this.polyline.get_name() }}.setText( "{{this.text}}", {{ this.options|tojson }} ); """) expected = normalize(tmpl.render(this=wind_textpath)) assert expected in out
def test_vectorgrid_str_options(): m = folium.Map(location=(30, 20), zoom_start=4) url = "https://free-{s}.tilehosting.com/data/v3/{z}/{x}/{y}.pbf?token={token}" options = """{ "subdomain": "test", "token": "test_token", "vectorTileLayerStyles": { "all": { "fill": true, "weight": 1, "fillColor": "green", "color": "black", "fillOpacity": 0.6, "opacity": 0.6 } } }""" vc = VectorGridProtobuf(url, "test", options) m.add_child(vc) dict_options = json.loads(options) out = normalize(m._parent.render()) script = f'<script src="{VectorGridProtobuf.default_js[0][1]}"></script>' assert script in out assert url in out assert "L.vectorGrid.protobuf" in out assert '"token": "test_token"' in out assert '"subdomain": "test"' in out for k, v in dict_options["vectorTileLayerStyles"]["all"].items(): if type(v) == bool: assert f'"{k}": {str(v).lower()}' in out continue if type(v) == str: assert f'"{k}": "{v}"' in out continue assert f'"{k}": {v}' in out
def test_polylineoffset(offset): m = folium.Map([20.0, 0.0], zoom_start=3) locations = [ [59.355600, -31.99219], [55.178870, -42.89062], [47.754100, -43.94531], [38.272690, -37.96875], [27.059130, -41.13281], [16.299050, -36.56250], [8.4071700, -30.23437], [1.0546300, -22.50000], [-8.754790, -18.28125], [-21.61658, -20.03906], [-31.35364, -24.25781], [-39.90974, -30.93750], [-43.83453, -41.13281], [-47.75410, -49.92187], [-50.95843, -54.14062], [-55.97380, -56.60156], ] polylineoffset = plugins.PolyLineOffset(locations=locations, offset=offset) polylineoffset.add_to(m) m._repr_html_() out = m._parent.render() # We verify that the script import is present. script = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/leaflet.polylineoffset.min.js"></script>' # noqa assert script in out # We verify that the script part is correct. expected_rendered = """ var {name} = L.polyline( {locations}, {{ "bubblingMouseEvents": true, "color": "#3388ff", "dashArray": null, "dashOffset": null, "fill": false, "fillColor": "#3388ff", "fillOpacity": 0.2, "fillRule": "evenodd", "lineCap": "round", "lineJoin": "round", "noClip": false, "offset": {offset}, "opacity": 1.0, "smoothFactor": 1.0, "stroke": true, "weight": 3 }} ) .addTo({map}); """.format( locations=locations, name=polylineoffset.get_name(), offset=offset, map=m.get_name(), ) rendered = polylineoffset._template.module.script(polylineoffset) assert normalize(expected_rendered) == normalize(rendered)
def test_timestamped_geo_json(): coordinates = [[[[lon - 8 * np.sin(theta), -47 + 6 * np.cos(theta)] for theta in np.linspace(0, 2 * np.pi, 25)], [[lon - 4 * np.sin(theta), -47 + 3 * np.cos(theta)] for theta in np.linspace(0, 2 * np.pi, 25)]] for lon in np.linspace(-150, 150, 7)] data = { 'type': 'FeatureCollection', 'features': [ { 'type': 'Feature', 'geometry': { 'type': 'Point', 'coordinates': [0, 0], }, 'properties': { 'times': [1435708800000 + 12 * 86400000] } }, { 'type': 'Feature', 'geometry': { 'type': 'MultiPoint', 'coordinates': [[lon, -25] for lon in np.linspace(-150, 150, 49)], }, 'properties': { 'times': [ 1435708800000 + i * 86400000 for i in np.linspace(0, 25, 49) ] } }, { 'type': 'Feature', 'geometry': { 'type': 'LineString', 'coordinates': [[lon, 25] for lon in np.linspace(-150, 150, 25)], }, 'properties': { 'times': [ 1435708800000 + i * 86400000 for i in np.linspace(0, 25, 25) ], 'style': { 'color': 'red' }, }, }, { 'type': 'Feature', 'geometry': { 'type': 'MultiLineString', 'coordinates': [[[lon - 4 * np.sin(theta), 47 + 3 * np.cos(theta)] for theta in np.linspace(0, 2 * np.pi, 25)] for lon in np.linspace(-150, 150, 13)], }, 'properties': { 'times': [ 1435708800000 + i * 86400000 for i in np.linspace(0, 25, 13) ] } }, { 'type': 'Feature', 'geometry': { 'type': 'MultiPolygon', 'coordinates': coordinates, }, 'properties': { 'times': [ 1435708800000 + i * 86400000 for i in np.linspace(0, 25, 7) ] } }, ], } m = folium.Map([47, 3], zoom_start=1) tgj = plugins.TimestampedGeoJson(data).add_to(m) out = normalize(m._parent.render()) # Verify the imports. assert '<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>' in out assert '<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js"></script>' in out assert '<script src="https://cdn.jsdelivr.net/npm/[email protected]/iso8601.min.js"></script>' in out assert '<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.timedimension.min.js"></script>' in out # noqa assert '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/default.min.css"/>' in out # noqa assert '<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.timedimension.control.css"/>' in out # noqa assert '<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>' in out # Verify that the script is okay. tmpl = Template(""" L.Control.TimeDimensionCustom = L.Control.TimeDimension.extend({ _getDisplayDateFormat: function(date){ var newdate = new moment(date); console.log(newdate) return newdate.format("{{this.date_options}}"); } }); {{this._parent.get_name()}}.timeDimension = L.timeDimension( { period: {{ this.period|tojson }}, } ); var timeDimensionControl = new L.Control.TimeDimensionCustom( {{ this.options|tojson }} ); {{this._parent.get_name()}}.addControl(this.timeDimensionControl); var geoJsonLayer = L.geoJson({{this.data}}, { pointToLayer: function (feature, latLng) { if (feature.properties.icon == 'marker') { if(feature.properties.iconstyle){ return new L.Marker(latLng, { icon: L.icon(feature.properties.iconstyle)}); } //else return new L.Marker(latLng); } if (feature.properties.icon == 'circle') { if (feature.properties.iconstyle) { return new L.circleMarker(latLng, feature.properties.iconstyle) }; //else return new L.circleMarker(latLng); } //else return new L.Marker(latLng); }, style: function (feature) { return feature.properties.style; }, onEachFeature: function(feature, layer) { if (feature.properties.popup) { layer.bindPopup(feature.properties.popup); } if (feature.properties.tooltip) { layer.bindTooltip(feature.properties.tooltip); } } }) var {{this.get_name()}} = L.timeDimension.layer.geoJson( geoJsonLayer, { updateTimeDimension: true, addlastPoint: {{ this.add_last_point|tojson }}, duration: {{ this.duration }}, } ).addTo({{this._parent.get_name()}}); """) # noqa expected = normalize(tmpl.render(this=tgj)) assert expected in out bounds = m.get_bounds() assert bounds == [[-53.0, -158.0], [50.0, 158.0]], bounds
def test_rectangle(): m = Map() location = [[45.6, -122.8], [45.61, -122.7]] rectangle = Rectangle( bounds=location, popup='I am a rectangle', color='black', weight=2, fill_opacity=0.6, opacity=1, fill=True, ) rectangle.add_to(m) expected_options = { 'bubblingMouseEvents': True, 'color': 'black', 'dashArray': None, 'dashOffset': None, 'fill': True, 'fillColor': 'black', 'fillOpacity': 0.6, 'fillRule': 'evenodd', 'lineCap': 'round', 'lineJoin': 'round', 'noClip': False, 'opacity': 1, 'smoothFactor': 1.0, 'stroke': True, 'weight': 2, } m._repr_html_() expected_rendered = """ var {name} = L.rectangle( {location}, {{ "bubblingMouseEvents": true, "color": "black", "dashArray": null, "dashOffset": null, "fill": true, "fillColor": "black", "fillOpacity": 0.6, "fillRule": "evenodd", "lineCap": "round", "lineJoin": "round", "noClip": false, "opacity": 1, "smoothFactor": 1.0, "stroke": true, "weight": 2 }} ) .addTo({map}); """.format(name=rectangle.get_name(), location=location, map=m.get_name()) rendered = rectangle._template.module.script(rectangle) assert normalize(rendered) == normalize(expected_rendered) assert rectangle.get_bounds() == location assert json.dumps(rectangle.to_dict()) == rectangle.to_json() assert rectangle.options == expected_options
def test_heat_map_with_time(): np.random.seed(3141592) initial_data = (np.random.normal(size=(100, 2)) * np.array([[1, 1]]) + np.array([[48, 5]])) move_data = np.random.normal(size=(100, 2)) * 0.01 data = [(initial_data + move_data * i).tolist() for i in range(100)] m = folium.Map([48., 5.], tiles='stamentoner', zoom_start=6) hm = plugins.HeatMapWithTime(data).add_to(m) out = normalize(m._parent.render()) # We verify that the script imports are present. script = '<script src="https://rawcdn.githack.com/socib/Leaflet.TimeDimension/master/dist/leaflet.timedimension.min.js"></script>' # noqa assert script in out script = '<script src="https://rawcdn.githack.com/python-visualization/folium/master/folium/templates/pa7_hm.min.js"></script>' # noqa assert script in out script = '<script src="https://rawcdn.githack.com/pa7/heatmap.js/develop/plugins/leaflet-heatmap/leaflet-heatmap.js"></script>' # noqa assert script in out script = '<link rel="stylesheet" href="http://apps.socib.es/Leaflet.TimeDimension/dist/leaflet.timedimension.control.min.css"/>' # noqa assert script in out # We verify that the script part is correct. tmpl = Template(""" var times = {{this.times}}; {{this._parent.get_name()}}.timeDimension = L.timeDimension( {times : times, currentTime: new Date(1)} ); var {{this._control_name}} = new L.Control.TimeDimensionCustom({{this.index}}, { autoPlay: {{this.auto_play}}, backwardButton: {{this.backward_button}}, displayDate: {{this.display_index}}, forwardButton: {{this.forward_button}}, limitMinimumRange: {{this.limit_minimum_range}}, limitSliders: {{this.limit_sliders}}, loopButton: {{this.loop_button}}, maxSpeed: {{this.max_speed}}, minSpeed: {{this.min_speed}}, playButton: {{this.play_button}}, playReverseButton: {{this.play_reverse_button}}, position: "{{this.position}}", speedSlider: {{this.speed_slider}}, speedStep: {{this.speed_step}}, styleNS: "{{this.style_NS}}", timeSlider: {{this.time_slider}}, timeSliderDrapUpdate: {{this.time_slider_drap_update}}, timeSteps: {{this.index_steps}} }) .addTo({{this._parent.get_name()}}); var {{this.get_name()}} = new TDHeatmap({{this.data}}, {heatmapOptions: { radius: {{this.radius}}, minOpacity: {{this.min_opacity}}, maxOpacity: {{this.max_opacity}}, scaleRadius: {{this.scale_radius}}, useLocalExtrema: {{this.use_local_extrema}}, defaultWeight: 1, {% if this.gradient %}gradient: {{ this.gradient }}{% endif %} } }) .addTo({{this._parent.get_name()}}); """) assert normalize(tmpl.render(this=hm)) in out
def test_polygon_marker(): m = Map() locations = [[35.6636, 139.7634], [35.6629, 139.7664], [35.6663, 139.7706], [35.6725, 139.7632], [35.6728, 139.7627], [35.6720, 139.7606], [35.6682, 139.7588], [35.6663, 139.7627]] polygon = Polygon(locations=locations, popup='I am a polygon') polygon.add_to(m) expected_options = { 'bubblingMouseEvents': True, 'color': '#3388ff', 'dashArray': None, 'dashOffset': None, 'fill': False, 'fillColor': '#3388ff', 'fillOpacity': 0.2, 'fillRule': 'evenodd', 'lineCap': 'round', 'lineJoin': 'round', 'noClip': False, 'opacity': 1.0, 'smoothFactor': 1.0, 'stroke': True, 'weight': 3, } m._repr_html_() expected_rendered = """ var {name} = L.polygon( {locations}, {{ "bubblingMouseEvents": true, "color": "#3388ff", "dashArray": null, "dashOffset": null, "fill": false, "fillColor": "#3388ff", "fillOpacity": 0.2, "fillRule": "evenodd", "lineCap": "round", "lineJoin": "round", "noClip": false, "opacity": 1.0, "smoothFactor": 1.0, "stroke": true, "weight": 3 }} ) .addTo({map}); """.format(locations=locations, name=polygon.get_name(), map=m.get_name()) rendered = polygon._template.module.script(polygon) assert normalize(rendered) == normalize(expected_rendered) assert polygon.get_bounds() == get_bounds(locations) assert json.dumps(polygon.to_dict()) == polygon.to_json() assert polygon.options == expected_options
def test_timestamped_geo_json(): coordinates = [[[[lon-8*np.sin(theta), -47+6*np.cos(theta)] for theta in np.linspace(0, 2*np.pi, 25)], [[lon-4*np.sin(theta), -47+3*np.cos(theta)] for theta in np.linspace(0, 2*np.pi, 25)]] for lon in np.linspace(-150, 150, 7)] data = { 'type': 'FeatureCollection', 'features': [ { 'type': 'Feature', 'geometry': { 'type': 'Point', 'coordinates': [0, 0], }, 'properties': { 'times': [1435708800000+12*86400000] } }, { 'type': 'Feature', 'geometry': { 'type': 'MultiPoint', 'coordinates': [[lon, -25] for lon in np.linspace(-150, 150, 49)], }, 'properties': { 'times': [1435708800000+i*86400000 for i in np.linspace(0, 25, 49)] } }, { 'type': 'Feature', 'geometry': { 'type': 'LineString', 'coordinates': [[lon, 25] for lon in np.linspace(-150, 150, 25)], }, 'properties': { 'times': [1435708800000+i*86400000 for i in np.linspace(0, 25, 25)], 'style': { 'color': 'red' }, }, }, { 'type': 'Feature', 'geometry': { 'type': 'MultiLineString', 'coordinates': [[[lon-4*np.sin(theta), 47+3*np.cos(theta)] for theta in np.linspace(0, 2*np.pi, 25)] for lon in np.linspace(-150, 150, 13)], }, 'properties': { 'times': [1435708800000+i*86400000 for i in np.linspace(0, 25, 13)] } }, { 'type': 'Feature', 'geometry': { 'type': 'MultiPolygon', 'coordinates': coordinates, }, 'properties': { 'times': [1435708800000+i*86400000 for i in np.linspace(0, 25, 7)] } }, ], } m = folium.Map([47, 3], zoom_start=1) tgj = plugins.TimestampedGeoJson(data).add_to(m) out = normalize(m._parent.render()) # Verify the imports. assert '<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>' in out assert '<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js"></script>' in out assert '<script src="https://rawcdn.githack.com/nezasa/iso8601-js-period/master/iso8601.min.js"></script>' in out assert '<script src="https://rawcdn.githack.com/socib/Leaflet.TimeDimension/master/dist/leaflet.timedimension.min.js"></script>' in out # noqa assert '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/default.min.css"/>' in out # noqa assert '<link rel="stylesheet" href="https://rawcdn.githack.com/socib/Leaflet.TimeDimension/master/dist/leaflet.timedimension.control.min.css"/>' in out # noqa assert '<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>' in out # Verify that the script is okay. tmpl = Template(""" L.Control.TimeDimensionCustom = L.Control.TimeDimension.extend({ _getDisplayDateFormat: function(date){ var newdate = new moment(date); console.log(newdate) return newdate.format("{{this.date_options}}"); } }); {{this._parent.get_name()}}.timeDimension = L.timeDimension( { period: {{ this.period|tojson }}, } ); var timeDimensionControl = new L.Control.TimeDimensionCustom( {{ this.options|tojson }} ); {{this._parent.get_name()}}.addControl(this.timeDimensionControl); var geoJsonLayer = L.geoJson({{this.data}}, { pointToLayer: function (feature, latLng) { if (feature.properties.icon == 'marker') { if(feature.properties.iconstyle){ return new L.Marker(latLng, { icon: L.icon(feature.properties.iconstyle)}); } //else return new L.Marker(latLng); } if (feature.properties.icon == 'circle') { if (feature.properties.iconstyle) { return new L.circleMarker(latLng, feature.properties.iconstyle) }; //else return new L.circleMarker(latLng); } //else return new L.Marker(latLng); }, style: function (feature) { return feature.properties.style; }, onEachFeature: function(feature, layer) { if (feature.properties.popup) { layer.bindPopup(feature.properties.popup); } } }) var {{this.get_name()}} = L.timeDimension.layer.geoJson( geoJsonLayer, { updateTimeDimension: true, addlastPoint: {{ this.add_last_point|tojson }}, duration: {{ this.duration }}, } ).addTo({{this._parent.get_name()}}); """) # noqa expected = normalize(tmpl.render(this=tgj)) assert expected in out bounds = m.get_bounds() assert bounds == [[-53.0, -158.0], [50.0, 158.0]], bounds
def test_circle_marker(): m = Map() radius = 50 popup = 'I am {} pixels'.format(radius) location = [-27.55, -48.8] circle_marker = CircleMarker( location=location, radius=radius, color='black', weight=2, fill_opacity=0.6, opacity=1, fill=True, popup=popup, ) circle_marker.add_to(m) options = { 'bubblingMouseEvents': True, 'color': 'black', 'dashArray': None, 'dashOffset': None, 'fill': True, 'fillColor': 'black', 'fillOpacity': 0.6, 'fillRule': 'evenodd', 'lineCap': 'round', 'lineJoin': 'round', 'opacity': 1, 'radius': radius, 'stroke': True, 'weight': 2, } m._repr_html_() expected_bounds = [location, location] expected_rendered = """ var {name} = L.circleMarker( {location}, {{ "bubblingMouseEvents": true, "color": "black", "dashArray": null, "dashOffset": null, "fill": true, "fillColor": "black", "fillOpacity": 0.6, "fillRule": "evenodd", "lineCap": "round", "lineJoin": "round", "opacity": 1, "radius": {radius}, "stroke": true, "weight": 2 }} ) .addTo({map}); """.format(name=circle_marker.get_name(), location=location, radius=radius, map=m.get_name()) # noqa rendered = circle_marker._template.module.script(circle_marker) assert normalize(rendered) == normalize(expected_rendered) assert circle_marker.get_bounds() == expected_bounds assert json.dumps(circle_marker.to_dict()) == circle_marker.to_json() assert circle_marker.location == location assert circle_marker.options == options