import streamlit as st import leafmap.foliumap as leafmap import json import requests # Functions to dynamically fetch columns def get_columns_from_geojson(geojson_data): """Retrieve column names from a GeoJSON data.""" if "features" in geojson_data: properties = geojson_data["features"][0]["properties"] return list(properties.keys()) return [] def get_columns_from_url(url): """Retrieve column names from a GeoJSON URL.""" response = requests.get(url) geojson_data = response.json() return get_columns_from_geojson(geojson_data) st.set_page_config(layout="wide") # Sidebar Information st.sidebar.info( ''' - Web App URL: - HuggingFace repository: ''' ) st.sidebar.title("Contact") st.sidebar.info( ''' Yunus Serhat Bıçakçı at [yunusserhat.com](https://yunusserhat.com) | [GitHub](https://github.com/yunusserhat) | [Twitter](https://twitter.com/yunusserhat) | [LinkedIn](https://www.linkedin.com/in/yunusserhat) ''' ) # Title and Description st.title("Interactive Analysis of Hate Metrics in London & Custom Dataset Visualization") st.markdown( ''' Dive into an interactive analysis of hate metrics in London, exploring the disparities and correlations between hate-related tweets and reported crimes in boroughs. This platform offers a comparative visualization based on data from X and the London Metropolitan Police Service as of December 2022. Additionally, users can upload and visualize their own GeoJSON datasets, facilitating personalized analysis and insights. Delve deeper into the patterns of hate sentiment, understand how online behavior might mirror real-world incidents, or uncover patterns in your own data. ''' ) # File Uploader uploaded_file = st.file_uploader("Upload a GeoJSON file", type=["geojson"]) uploaded_geojson = None # Map URLs map_1 = "https://raw.githubusercontent.com/yunusserhat/data/main/data/boroughs_count_df_2022_dec.geojson" map_2 = "https://raw.githubusercontent.com/yunusserhat/data/main/data/mps_hate_2022_dec_count.geojson" map_3 = "https://raw.githubusercontent.com/yunusserhat/data/main/data/mps2022dec_count.geojson" if uploaded_file: try: uploaded_geojson = json.load(uploaded_file) if "features" not in uploaded_geojson: st.warning("The uploaded file does not seem to be a valid GeoJSON format.") uploaded_geojson = None else: st.success("GeoJSON file uploaded successfully!") except json.JSONDecodeError: st.error("Failed to decode the uploaded file. Please ensure it's a valid GeoJSON format.") # Map Selection map_choices = ["Hate Tweets", "MPS Hate Crime Data", "MPS All Crime Data"] if uploaded_geojson: map_choices.append("Uploaded GeoJSON") selected_map_1 = st.selectbox("Select data for Map 1", map_choices) # Determine the columns based on the selected dataset for Map 1 if selected_map_1 == "Uploaded GeoJSON" and uploaded_geojson: available_columns_1 = get_columns_from_geojson(uploaded_geojson) elif selected_map_1 == "Hate Tweets": available_columns_1 = get_columns_from_url(map_1) elif selected_map_1 == "MPS Hate Crime Data": available_columns_1 = get_columns_from_url(map_2) elif selected_map_1 == "MPS All Crime Data": available_columns_1 = get_columns_from_url(map_3) selected_column_1 = st.selectbox("Select column for Map 1 visualization", available_columns_1) selected_map_2 = st.selectbox("Select data for Map 2", map_choices) # Determine the columns based on the selected dataset for Map 2 if selected_map_2 == "Uploaded GeoJSON" and uploaded_geojson: available_columns_2 = get_columns_from_geojson(uploaded_geojson) elif selected_map_2 == "Hate Tweets": available_columns_2 = get_columns_from_url(map_1) elif selected_map_2 == "MPS Hate Crime Data": available_columns_2 = get_columns_from_url(map_2) elif selected_map_2 == "MPS All Crime Data": available_columns_2 = get_columns_from_url(map_3) selected_column_2 = st.selectbox("Select column for Map 2 visualization", available_columns_2) # Display Maps row1_col1, row1_col2 = st.columns([1, 1]) with row1_col1: m1 = leafmap.Map(center=[51.50, -0.1], zoom=10) if selected_map_1 == "Uploaded GeoJSON": m1.add_data(uploaded_geojson, column=selected_column_1) elif selected_map_1 == "Hate Tweets": m1.add_data(map_1, column=selected_column_1) elif selected_map_1 == "MPS Hate Crime Data": m1.add_data(map_2, column=selected_column_1) else: m1.add_data(map_3, column=selected_column_1) with row1_col2: m2 = leafmap.Map(center=[51.50, -0.1], zoom=10) if selected_map_2 == "Uploaded GeoJSON": m2.add_data(uploaded_geojson, column=selected_column_2) elif selected_map_2 == "Hate Tweets": m2.add_data(map_1, column=selected_column_2) elif selected_map_2 == "MPS Hate Crime Data": m2.add_data(map_2, column=selected_column_2) else: m2.add_data(map_3, column=selected_column_2) # Zoom longitude = -0.1 latitude = 51.50 zoomlevel = st.number_input("Zoom", 0, 20, 10) row2_col1, row2_col2 = st.columns([1, 1]) with row2_col1: m1.set_center(longitude, latitude, zoomlevel) with row2_col2: m2.set_center(longitude, latitude, zoomlevel) row3_col1, row3_col2 = st.columns([1, 1]) with row3_col1: m1.to_streamlit() with row3_col2: m2.to_streamlit()