Genie Discord forum

Author AvatarGareth
10/2/2023, 6:13:55 AM

I am trying to use Genie as a way to plot number of Julia Packages per city. I would like to have a way to draw a map and have a circle based on number of packages in a city (number of packages that were initially developed in a city). With Plotly I believe I have to search for lat/long for each city... this is not so convinient. Is there any other way?

Author AvatarPere
10/2/2023, 1:13:41 PM

You could use the OpenStreetMaps API to get the coordinates for a city. Here's an example

using HTTP
using JSON

# Replace with a specific city or address
location = "Amsterdam, Netherlands"

# Make a GET request to the Nominatim API
url = "https://nominatim.openstreetmap.org/search?format=json&q=$(escape(location))"
headers = ["User-Agent" => "YourAppName (your@email.com)"]
response = HTTP.get(url, headers)

# Parse the JSON response
data = JSON.parse(String(response.body))

# Extract latitude and longitude
if length(data) > 0
    lat = data[1]["lat"]
    lon = data[1]["lon"]
    println("Latitude: $lat, Longitude: $lon")
else
    println("Location not found")
end
Author AvatarPere
10/2/2023, 1:15:07 PM

Also, I played around with the maps so here's an example to help get you started. You'll need to set up a mapbox account and get the token

module App
using PlotlyBase
using GenieFramework
@genietools
cities_coordinates = Dict(
    "Amsterdam" => [52.3676, 4.9041],
    "Rotterdam" => [51.9225, 4.47917],
    "The Hague" => [52.0787, 4.2888],
    "Utrecht" => [52.0843, 5.0128],
    "Eindhoven" => [51.4416, 5.4697]
)
N = length(cities_coordinates)
names = keys(cities_coordinates)
lats = [v[1] for v in values(cities_coordinates)]
longs = [v[2] for v in values(cities_coordinates)]

@app begin
    @out trace = [
        scattermapbox(
            lon=longs,
            lat=lats,
            text=names,
            mode="markers+text",
            marker=attr(size=abs.(randn(N)) * 10 .+ 4, color="blue"),
            textposition="bottom right"
        )
    ]
    @out layout = PlotlyBase.Layout(
        title="World Map",
        showlegend=false,
        width=800,
        height=800,
        mapbox=attr(
            accesstoken="",
            style="light",
            center=attr(lat=52.0, lon=5.0),  # Center the map to the Netherlands
            zoom=6.5  # Adjust the zoom level as needed
        )
    )

    # this is for detecting click events
    @in data_click = Dict{String,Any}()  # data from map click event
    @in data_cursor = Dict{String,Any}()

    @onchange data_click begin
        @show data_click
        @show data_cursor
    end
end

# activate detection of click events
@mounted watchplots()

ui() = plot(:trace, layout=:layout, class="sync_data")
@page("/", ui)
end
Author AvatarPere
10/2/2023, 1:16:36 PM

In case you dont want to use mapbox you can use plotly's geo, but the map is uglier

    @out trace = [
        scattergeo(
            locationmode="ISO-3",
            lon=longs,
            lat=lats,
            text=names,
            textposition="bottom right",
            textfont=attr(family="Arial Black", size=18, color="blue"),
            mode="markers+text",
            marker=attr(size=abs.(randn(N) * 20), color="blue"),
            name="Cities"),
    ]
    @out layout = PlotlyBase.Layout(
        title="World Map",
        showlegend=false,
        width=800,
        height=800,
        geo=attr(
            resolution=50,
            showframe=false,
            #= scope="europe", =#
            showcountries=true,
            showsubunits=true,
            showlakes=true,
            projection=attr(type="natural earth"),
            lonaxis=attr(range=[3.4, 7.2]),
            lataxis=attr(range=[50.5, 54])
        )
    )
Author AvatarGareth
10/16/2023, 4:12:45 PM

Awesome!!! Going to try it this weekend:)