Search code examples
pythonflaskgeojsonfolium

Displaying geojson data sent by flask server in folium map


I am currently working on a teaching tool for aviation and I need to display realtime data in a 1s interval in a GUI on a map. I decided to use PySide6 and folium for this. The realtime data is simple position data consisting of latitude and longitude. To my understanding it is not possible to insert changing values from the simulation right into the folium Realtime function, but to fetch it from an endpoint. The exampledata provided in the documentation works and displays data as expected in the map from this source: https://raw.githubusercontent.com/python-visualization/folium-example-data/main/subway_stations.geojson I set up a flask_server to send randomized data as a proof of concept, but the data doesn't show in the map. Down below the function, which contains the Realtime access

def plot_flight_path(self):
    # Create a Folium map centered at the start of the path
    self.m = folium.Map(location=[self.start[0], self.start[1]], zoom_start=5)
    # Add the satellite imagery layer from Google Maps API
    folium.TileLayer('https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', attr='Google Satellite',
                     name='Google Satellite', overlay=True).add_to(self.m)

    # Plot the path as a Polyline on the map
    folium.PolyLine(locations=self.route, color='blue', weight=5).add_to(self.m)
    rt = folium.plugins.Realtime(
        "http://127.0.0.1:5000/random_position.geojson",
        get_feature_id=JsCode("(f) => { return f.properties.objectid; }"),
        interval=10000,
    )
    #rt = Realtime("http://127.0.0.1:5000/", interval=1000)
    rt.add_to(self.m)

    # Convert the Folium map to HTML
    plot_html = self.m.get_root().render()

    # Load the Folium map in the web view
    self.webview.setHtml(plot_html)

And the flask_server I set up:

from flask import Flask, jsonify
import random

app = Flask(__name__)

@app.route('/random_position.geojson')
def random_position():
    # Generate random latitude and longitude
    latitude1 = random.uniform(-90, 90)
    longitude1 = random.uniform(-180, 180)
    latitude2 = random.uniform(-90, 90)
    longitude2 = random.uniform(-180, 180)

    # Create GeoJSON FeatureCollection with unordered features
    features = [
        {
            "type": "Feature",
            "properties": {
                "name": "Astor Pl",
                "url": "http://web.mta.info/nyct/service/",
                "line": "4-6-6 Express",
                "objectid": "1",
                "notes": "4 nights, 6-all times, 6 Express-weekdays AM southbound, PM northbound"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [latitude1, longitude1]
            }
        },
        {
            "type": "Feature",
            "properties": {
                "name": "Canal St",
                "url": "http://web.mta.info/nyct/service/",
                "line": "4-6-6 Express",
                "objectid": "2",
                "notes": "4 nights, 6-all times, 6 Express-weekdays AM southbound, PM northbound"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [latitude2, longitude2]
            }
        }
    ]

    # Create GeoJSON FeatureCollection
    feature_collection = {
        "type": "FeatureCollection",
        "features": features
    }

    print("Returning GeoJSON:", feature_collection)

    return jsonify(feature_collection), 200, {'Content-Type': 'application/json'}

if __name__ == '__main__':
    app.run(debug=True, port=5000)

I changed many parameters beginning in accessing the flask server via the JsCode function in folium and I changed different parameters in the flask_server file. Additionally i tried to send a .geojson file, not only the formatted geojson data, but this didn't work either.

Thanks in advance!


Solution

  • I could resolve the issue by adding a header, which is needed by the fetch function:

    with open('random_position.geojson', 'w') as f:
       json.dump(feature_collection, f) 
    response = make_response(send_file('random_position.geojson',
                                       mimetype='application/json'))
    response.headers.add('Access-Control-Allow-Origin',
                         '*')
    return response