opengeos / leafmap

A Python package for interactive mapping and geospatial analysis with minimal coding in a Jupyter environment
https://leafmap.org
MIT License
3.11k stars 369 forks source link

Add support for Gradio #362

Closed giswqs closed 1 year ago

giswqs commented 1 year ago

Gradio is a Python package for building interactive web apps to demo machine learning models. It supports bokeh and plotly. It would be great to add leafmap support for this.

https://gradio.app/plot-component-for-maps/

giswqs commented 1 year ago

A simple Gradio web app for visualizing COG with leafmap

import gradio as gr
import leafmap.plotlymap as leafmap

def create_map(url):
    m = leafmap.Map()
    m.add_cog_layer(url)
    return m   

url = 'https://opendata.digitalglobe.com/events/california-fire-2020/pre-event/2018-02-16/pine-gulch-fire20/1030010076004E00.tif'

demo = gr.Interface(
    fn=create_map,
    inputs=gr.Text(value=url, label='Enter a COG URL'),
    outputs=gr.Plot().style(),
)
demo.launch()

https://user-images.githubusercontent.com/5016453/218625821-a4ef18b1-3a47-476f-b95d-d566e2492044.mp4

giswqs commented 1 year ago

An Earthquake heatmap example.

import gradio as gr
import leafmap.plotlymap as leafmap

def create_map(url, latitude, longitude, z):
    m = leafmap.Map()
    m.add_heatmap(url, latitude, longitude, z)
    return m   

url = 'https://raw.githubusercontent.com/plotly/datasets/master/earthquakes-23k.csv'

demo = gr.Interface(
    fn=create_map,
    inputs=[gr.Text(value=url, label='Enter a URL'), 
            gr.Text(value='Latitude', label='Latitude column'), 
            gr.Text(value='Longitude', label='Longitude column'),
            gr.Text(value='Magnitude', label='Value column')],
    outputs=gr.Plot().style(),
)
demo.launch()

https://user-images.githubusercontent.com/5016453/218628803-5c87568c-6425-4fd3-83cb-47baa761bc22.mp4

giswqs commented 1 year ago

A split control example.

https://user-images.githubusercontent.com/5016453/218933780-da47f80a-52dc-49e4-9305-bdd71ddd4d5e.mp4

import gradio as gr

def test(x):
    x = """
<!DOCTYPE html>
<html>
<head>

    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />

        <script>
            L_NO_TOUCH = false;
            L_DISABLE_3D = false;
        </script>

    <style>html, body {width: 100%;height: 100%;margin: 0;padding: 0;}</style>
    <style>#map {position:absolute;top:0;bottom:0;right:0;left:0;}</style>
    <script src="https://cdn.jsdelivr.net/npm/leaflet@1.6.0/dist/leaflet.js"></script>
    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.6.0/dist/leaflet.css"/>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"/>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css"/>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css"/>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css"/>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css"/>

            <meta name="viewport" content="width=device-width,
                initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
            <style>
                #map_ab9fed1eb8a2169ece7fc97e9b1352b9 {
                    position: relative;
                    width: 100.0%;
                    height: 100.0%;
                    left: 0.0%;
                    top: 0.0%;
                }
            </style>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.fullscreen/1.4.2/Control.FullScreen.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.fullscreen/1.4.2/Control.FullScreen.min.css"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.css"/>
    <script src="https://cdn.jsdelivr.net/gh/ljagis/leaflet-measure@2.1.7/dist/leaflet-measure.min.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/ljagis/leaflet-measure@2.1.7/dist/leaflet-measure.min.css"/>
    <script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.css"/>
    <script src="https://cdn.jsdelivr.net/gh/digidem/leaflet-side-by-side@gh-pages/leaflet-side-by-side.min.js"></script>
</head>
<body>

            <div class="folium-map" id="map_ab9fed1eb8a2169ece7fc97e9b1352b9" ></div>

</body>
<script>

            var map_ab9fed1eb8a2169ece7fc97e9b1352b9 = L.map(
                "map_ab9fed1eb8a2169ece7fc97e9b1352b9",
                {
                    center: [20.0, 0.0],
                    crs: L.CRS.EPSG3857,
                    zoom: 2,
                    zoomControl: true,
                    preferCanvas: false,
                    drawExport: false,
                    layersControl: true,
                }
            );
            L.control.scale().addTo(map_ab9fed1eb8a2169ece7fc97e9b1352b9);            

            var tile_layer_5b5a43882783f7eae3e0b9e6af3f0150 = L.tileLayer(
                "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
                // {"attribution": "Data by \u0026copy; \u003ca href=\"http://openstreetmap.org\"\u003eOpenStreetMap\u003c/a\u003e, under \u003ca href=\"http://www.openstreetmap.org/copyright\"\u003eODbL\u003c/a\u003e.", "detectRetina": false, "maxNativeZoom": 24, "maxZoom": 24, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
            ).addTo(map_ab9fed1eb8a2169ece7fc97e9b1352b9);

            L.control.fullscreen(
                {"forceSeparateButton": false, "position": "topleft", "title": "Full Screen", "titleCancel": "Exit Full Screen"}
            ).addTo(map_ab9fed1eb8a2169ece7fc97e9b1352b9);

            var options = {
              position: "topleft",
              draw: {},
              edit: {},/*  */
            }
            // FeatureGroup is to store editable layers.
            var drawnItems = new L.featureGroup().addTo(
                map_ab9fed1eb8a2169ece7fc97e9b1352b9
            );
            options.edit.featureGroup = drawnItems;
            var draw_control_256b8df540bca4a2ca2fd2ed1a14d56f = new L.Control.Draw(
                options
            ).addTo( map_ab9fed1eb8a2169ece7fc97e9b1352b9 );

            var measure_control_49ef44a4c2e5f53af86ee2298aa90f58 = new L.Control.Measure(
                {"position": "bottomleft", "primaryAreaUnit": "sqmeters", "primaryLengthUnit": "meters", "secondaryAreaUnit": "acres", "secondaryLengthUnit": "miles"});
            map_ab9fed1eb8a2169ece7fc97e9b1352b9.addControl(measure_control_49ef44a4c2e5f53af86ee2298aa90f58);

            map_ab9fed1eb8a2169ece7fc97e9b1352b9.fitBounds(
                [[20, 0], [20, 0]],
                {"maxZoom": 2}
            );

            var tile_layer_9afa18cd9734a50057cdb08748177929 = L.tileLayer(
                "https://mt1.google.com/vt/lyrs=p\u0026x={x}\u0026y={y}\u0026z={z}",
                {"attribution": "Google", "detectRetina": false, "maxNativeZoom": 22, "maxZoom": 22, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
            ).addTo(map_ab9fed1eb8a2169ece7fc97e9b1352b9);

            var tile_layer_5235882ec753b573e80e207ed21d712a = L.tileLayer(
                "https://a.tile.opentopomap.org/{z}/{x}/{y}.png",
                {"attribution": "Map data: (C) OpenStreetMap contributors, SRTM | Map style: (C) OpenTopoMap (CC-BY-SA)", "detectRetina": false, "maxNativeZoom": 17, "maxZoom": 17, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
            ).addTo(map_ab9fed1eb8a2169ece7fc97e9b1352b9);

            var side_by_side_layers_3661f6115c93abc79c48e752e144bcf7 = L.control.sideBySide(
                tile_layer_9afa18cd9734a50057cdb08748177929, tile_layer_5235882ec753b573e80e207ed21d712a
            ).addTo(map_ab9fed1eb8a2169ece7fc97e9b1352b9);

            var layer_control_20e4a56c9953f31d1b97bd2d7d9457d6 = {
                base_layers : {
                    "openstreetmap" : tile_layer_5b5a43882783f7eae3e0b9e6af3f0150,
                },
                overlays :  {
                    "Google Terrain" : tile_layer_9afa18cd9734a50057cdb08748177929,
                    "OpenTopoMap" : tile_layer_5235882ec753b573e80e207ed21d712a,
                },
            };
            L.control.layers(
                layer_control_20e4a56c9953f31d1b97bd2d7d9457d6.base_layers,
                layer_control_20e4a56c9953f31d1b97bd2d7d9457d6.overlays,
                {"autoZIndex": true, "collapsed": true, "position": "topright"}
            ).addTo(map_ab9fed1eb8a2169ece7fc97e9b1352b9);

</script>
</html>
"""

    return f"""<iframe style="width: 100%; height: 480px" name="result" allow="midi; geolocation; microphone; camera; 
    display-capture; encrypted-media;" sandbox="allow-modals allow-forms 
    allow-scripts allow-same-origin allow-popups 
    allow-top-navigation-by-user-activation allow-downloads" allowfullscreen="" 
    allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>"""

gr.Interface(test, "text", "html").launch(debug=True)