import streamlit as st import geopandas as gpd import folium from streamlit_folium import folium_static from dotenv import load_dotenv from utils import get_provider_data import os import numpy as np import matplotlib.pyplot as plt import matplotlib.colors as mcolors from folium.features import CustomIcon # Load environment variables load_dotenv() # Set page config for dark theme st.set_page_config( page_title="Europeana Data Explorer", page_icon="🌍", layout="wide", initial_sidebar_state="expanded", ) # Load CSS file def load_css(file_name): with open(file_name) as f: st.markdown(f'', unsafe_allow_html=True) # Load the CSS load_css("style.css") # Ensure that the API key is set if 'EUROPEANA_API_KEY' not in os.environ: st.error("EUROPEANA_API_KEY is not set in the environment variables. Please set it and restart the app.") st.stop() # Load world map dataset world = gpd.read_file("lowres_world.geojson") # Set up the Streamlit app st.title('🌍 Europeana Data Explorer') # Sidebar st.sidebar.header("About") st.sidebar.info("This app allows you to explore data from Europeana providers. Enter a provider name to fetch and visualize their data across different countries.") # Add Europeana logo below the "About" section logo_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/Europeana_logo_2015_basic.svg/800px-Europeana_logo_2015_basic.svg.png" st.sidebar.image(logo_url, width=50) # Input for provider name provider_name = st.text_input('Enter the name of the data provider:', help="e.g., 'Rijksmuseum'") # Button to trigger data fetch if st.button('🔍 Fetch Data'): if provider_name: # Show loading message with st.spinner('Fetching data...'): # Get the data df, world_counts = get_provider_data(provider_name, world) # Display the data st.subheader(f'📊 Data from {provider_name}') st.write(f'Number of items retrieved: {len(df):,}') # Display the first few rows st.subheader('🔎 Sample Data:') st.dataframe(df.head(), use_container_width=True) # Create and display the choropleth map with st.expander('Object Counts by Country'): choropleth_map = folium.Map(location=[20, 0], zoom_start=2, tiles="cartodbpositron") # Apply log transformation to object_count world_counts['log_count'] = np.log1p(world_counts['object_count']) # Use a custom colormap colormap = plt.colormaps['Blues'] # Access the 'Blues' colormap norm = mcolors.Normalize( vmin=world_counts['log_count'].min(), vmax=world_counts['log_count'].max()) # Function to map log_count to a color using the colormap def get_color(log_count): return mcolors.to_hex(colormap(norm(log_count))) # Add the choropleth layer choropleth = folium.Choropleth( geo_data=world_counts, name='choropleth', data=world_counts, columns=['name', 'log_count'], key_on='feature.properties.name', fill_opacity=0.7, line_opacity=0.2, legend_name=None ) # Remove the existing color map from the choropleth object for key in choropleth._children: if key.startswith('color_map'): del (choropleth._children[key]) choropleth.add_to(choropleth_map) # Manually set the colors for each feature based on log_count using the # custom function for feature in choropleth.geojson.data['features']: log_count = feature['properties']['log_count'] feature['properties']['style'] = { 'fillColor': get_color(log_count)} # Add hover functionality def style_function(x): return {'fillColor': '#ffffff', 'color': '#000000', 'fillOpacity': 0.1, 'weight': 0.1} def highlight_function(x): return {'fillColor': '#ffffff', 'color': '#000000', 'fillOpacity': 0.50, 'weight': 0.1} info = folium.features.GeoJson( world_counts, style_function=style_function, control=False, highlight_function=highlight_function, tooltip=folium.features.GeoJsonTooltip( fields=['name', 'object_count'], aliases=['Country:', 'Number of Objects:'], style=( "background-color: #FFFFFF; color: #333333; font-family: arial; font-size: 12px; padding: 10px;") ) ) choropleth_map.add_child(info) choropleth_map.keep_in_front(info) folium_static(choropleth_map, width=500, height=500) # Sample the DataFrame to get 20 random entries sample_df = df.sample(n=min(20, len(df)), random_state=1) # Create and display the marker map with st.expander('Collection Objects on the Map'): marker_map = folium.Map(location=[20, 0], zoom_start=2, tiles="cartodbpositron") # Function to create a marker with an image def add_marker(row): image_url = row['edmPreview'] # URL to the image popup_html = f'' folium.Marker( location=[row['edmPlaceLatitude'], row['edmPlaceLongitude']], icon=CustomIcon(icon_image=image_url, icon_size=(50, 50)), popup=folium.Popup(popup_html, max_width=250) ).add_to(marker_map) # Apply the function to each row in the sampled DataFrame sample_df.apply(add_marker, axis=1) folium_static(marker_map, width=500, height=500) # Option to download the full dataset csv = df.to_csv(index=False) st.download_button( label="📥 Download full dataset as CSV", data=csv, file_name=f"{provider_name}_data.csv", mime="text/csv", ) else: st.warning('⚠️ Please enter a provider name.') # Run this app with: streamlit run app.py