Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -431,7 +431,7 @@ except ET.ParseError as e:
|
|
| 431 |
# -------------------------------
|
| 432 |
# Tabs for Different Views
|
| 433 |
# -------------------------------
|
| 434 |
-
tabs = st.tabs(["Raw XML", "DataFrame", "Diplomatic Edition", "Editor Edition", "Visualization"])
|
| 435 |
|
| 436 |
# -------------------------------
|
| 437 |
# Raw XML Tab
|
|
@@ -709,6 +709,162 @@ with tabs[4]:
|
|
| 709 |
place_desc = places_dict.get(row['Origin_ID'], {}).get('Description', "No description available.")
|
| 710 |
st.markdown(f"**Place Description**: {place_desc}")
|
| 711 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 712 |
# -------------------------------
|
| 713 |
# Footer
|
| 714 |
# -------------------------------
|
|
|
|
| 431 |
# -------------------------------
|
| 432 |
# Tabs for Different Views
|
| 433 |
# -------------------------------
|
| 434 |
+
tabs = st.tabs(["Raw XML", "DataFrame", "Diplomatic Edition", "Editor Edition", "Visualization", "Authority Connections"])
|
| 435 |
|
| 436 |
# -------------------------------
|
| 437 |
# Raw XML Tab
|
|
|
|
| 709 |
place_desc = places_dict.get(row['Origin_ID'], {}).get('Description', "No description available.")
|
| 710 |
st.markdown(f"**Place Description**: {place_desc}")
|
| 711 |
|
| 712 |
+
with tabs[5]:
|
| 713 |
+
st.subheader("Authority Connections")
|
| 714 |
+
|
| 715 |
+
# Define Authority Types
|
| 716 |
+
authority_types = ["Material", "Place"] # Extend this list if you include Titles in the future
|
| 717 |
+
|
| 718 |
+
# Select Authority Type
|
| 719 |
+
selected_authority_type = st.selectbox("Select Authority Type", authority_types)
|
| 720 |
+
|
| 721 |
+
# Based on selection, provide the corresponding options
|
| 722 |
+
if selected_authority_type == "Material":
|
| 723 |
+
# List all materials from materials_dict
|
| 724 |
+
material_names = [material['Name_EN'] for material in materials_dict.values()]
|
| 725 |
+
selected_material = st.selectbox("Select Material", sorted(material_names))
|
| 726 |
+
|
| 727 |
+
# Find the material ID based on the selected name
|
| 728 |
+
material_id = None
|
| 729 |
+
for id_, material in materials_dict.items():
|
| 730 |
+
if material['Name_EN'] == selected_material:
|
| 731 |
+
material_id = id_
|
| 732 |
+
break
|
| 733 |
+
|
| 734 |
+
if material_id:
|
| 735 |
+
# Filter inscriptions that reference this material
|
| 736 |
+
connected_inscriptions = df[df['Material_ID'] == material_id]
|
| 737 |
+
|
| 738 |
+
st.markdown(f"### Inscriptions using **{selected_material}**")
|
| 739 |
+
st.write(f"**Total Inscriptions:** {len(connected_inscriptions)}")
|
| 740 |
+
|
| 741 |
+
if not connected_inscriptions.empty:
|
| 742 |
+
# Display inscriptions in a table
|
| 743 |
+
st.dataframe(connected_inscriptions[['Number', 'Publisher', 'Origin', 'Language', 'Dating', 'Encoder']])
|
| 744 |
+
|
| 745 |
+
# Optional: Visualization - Number of Inscriptions per Year (Dating)
|
| 746 |
+
st.markdown("#### Inscriptions Over Time")
|
| 747 |
+
# Assuming 'Dating' is in a format that can be processed (e.g., single year or range)
|
| 748 |
+
# For simplicity, we'll extract the starting year
|
| 749 |
+
def extract_start_year(dating):
|
| 750 |
+
if isinstance(dating, str):
|
| 751 |
+
parts = dating.split('to')
|
| 752 |
+
try:
|
| 753 |
+
return int(parts[0].strip())
|
| 754 |
+
except:
|
| 755 |
+
return None
|
| 756 |
+
return None
|
| 757 |
+
|
| 758 |
+
connected_inscriptions['Start_Year'] = connected_inscriptions['Dating'].apply(extract_start_year)
|
| 759 |
+
year_counts = connected_inscriptions['Start_Year'].dropna().astype(int).value_counts().sort_index()
|
| 760 |
+
|
| 761 |
+
fig, ax = plt.subplots()
|
| 762 |
+
ax.bar(year_counts.index, year_counts.values, color='skyblue')
|
| 763 |
+
ax.set_xlabel('Year')
|
| 764 |
+
ax.set_ylabel('Number of Inscriptions')
|
| 765 |
+
ax.set_title(f'Number of Inscriptions Using {selected_material} Over Time')
|
| 766 |
+
st.pyplot(fig)
|
| 767 |
+
|
| 768 |
+
# Optional: Network Graph
|
| 769 |
+
st.markdown("#### Network Graph of Inscriptions and Materials")
|
| 770 |
+
G = nx.Graph()
|
| 771 |
+
|
| 772 |
+
# Add nodes
|
| 773 |
+
G.add_node(selected_material, type='Material')
|
| 774 |
+
for _, row in connected_inscriptions.iterrows():
|
| 775 |
+
inscription_node = f"Inscription {row['Number']}"
|
| 776 |
+
G.add_node(inscription_node, type='Inscription')
|
| 777 |
+
G.add_edge(selected_material, inscription_node)
|
| 778 |
+
|
| 779 |
+
# Define node colors based on type
|
| 780 |
+
color_map = []
|
| 781 |
+
for node in G:
|
| 782 |
+
if G.nodes[node]['type'] == 'Material':
|
| 783 |
+
color_map.append('lightblue')
|
| 784 |
+
else:
|
| 785 |
+
color_map.append('lightgreen')
|
| 786 |
+
|
| 787 |
+
# Draw the graph
|
| 788 |
+
plt.figure(figsize=(8, 6))
|
| 789 |
+
nx.draw(G, with_labels=True, node_color=color_map, node_size=1500, font_size=10, font_weight='bold')
|
| 790 |
+
st.pyplot(plt)
|
| 791 |
+
plt.close()
|
| 792 |
+
|
| 793 |
+
else:
|
| 794 |
+
st.info("No inscriptions found for the selected material.")
|
| 795 |
+
|
| 796 |
+
elif selected_authority_type == "Place":
|
| 797 |
+
# List all places from places_dict
|
| 798 |
+
place_names = [place['Name'] for place in places_dict.values()]
|
| 799 |
+
selected_place = st.selectbox("Select Place", sorted(place_names))
|
| 800 |
+
|
| 801 |
+
# Find the place ID based on the selected name
|
| 802 |
+
place_id = None
|
| 803 |
+
for id_, place in places_dict.items():
|
| 804 |
+
if place['Name'] == selected_place:
|
| 805 |
+
place_id = id_
|
| 806 |
+
break
|
| 807 |
+
|
| 808 |
+
if place_id:
|
| 809 |
+
# Filter inscriptions that originate from this place
|
| 810 |
+
connected_inscriptions = df[df['Origin_ID'] == place_id]
|
| 811 |
+
|
| 812 |
+
st.markdown(f"### Inscriptions from **{selected_place}**")
|
| 813 |
+
st.write(f"**Total Inscriptions:** {len(connected_inscriptions)}")
|
| 814 |
+
|
| 815 |
+
if not connected_inscriptions.empty:
|
| 816 |
+
# Display inscriptions in a table
|
| 817 |
+
st.dataframe(connected_inscriptions[['Number', 'Publisher', 'Material', 'Language', 'Dating', 'Encoder']])
|
| 818 |
+
|
| 819 |
+
# Optional: Visualization - Inscriptions Geographical Distribution
|
| 820 |
+
st.markdown("#### Geographical Distribution of Inscriptions")
|
| 821 |
+
map_df = connected_inscriptions[['Latitude', 'Longitude', 'Number']]
|
| 822 |
+
map_df = map_df.dropna(subset=['Latitude', 'Longitude'])
|
| 823 |
+
|
| 824 |
+
if not map_df.empty:
|
| 825 |
+
# Create a Folium map centered on the selected place
|
| 826 |
+
selected_place_coords = [places_dict[place_id]['Latitude'], places_dict[place_id]['Longitude']]
|
| 827 |
+
folium_map = folium.Map(location=selected_place_coords, zoom_start=8)
|
| 828 |
+
|
| 829 |
+
for _, row in map_df.iterrows():
|
| 830 |
+
folium.Marker(
|
| 831 |
+
location=[row['Latitude'], row['Longitude']],
|
| 832 |
+
popup=f"Inscription {row['Number']}"
|
| 833 |
+
).add_to(folium_map)
|
| 834 |
+
|
| 835 |
+
st_folium(folium_map, width=700, height=500)
|
| 836 |
+
else:
|
| 837 |
+
st.info("No geographical data available for these inscriptions.")
|
| 838 |
+
|
| 839 |
+
# Optional: Network Graph
|
| 840 |
+
st.markdown("#### Network Graph of Inscriptions and Places")
|
| 841 |
+
G = nx.Graph()
|
| 842 |
+
|
| 843 |
+
# Add nodes
|
| 844 |
+
G.add_node(selected_place, type='Place')
|
| 845 |
+
for _, row in connected_inscriptions.iterrows():
|
| 846 |
+
inscription_node = f"Inscription {row['Number']}"
|
| 847 |
+
G.add_node(inscription_node, type='Inscription')
|
| 848 |
+
G.add_edge(selected_place, inscription_node)
|
| 849 |
+
|
| 850 |
+
# Define node colors based on type
|
| 851 |
+
color_map = []
|
| 852 |
+
for node in G:
|
| 853 |
+
if G.nodes[node]['type'] == 'Place':
|
| 854 |
+
color_map.append('salmon')
|
| 855 |
+
else:
|
| 856 |
+
color_map.append('lightgreen')
|
| 857 |
+
|
| 858 |
+
# Draw the graph
|
| 859 |
+
plt.figure(figsize=(8, 6))
|
| 860 |
+
nx.draw(G, with_labels=True, node_color=color_map, node_size=1500, font_size=10, font_weight='bold')
|
| 861 |
+
st.pyplot(plt)
|
| 862 |
+
plt.close()
|
| 863 |
+
|
| 864 |
+
else:
|
| 865 |
+
st.info("No inscriptions found for the selected place.")
|
| 866 |
+
|
| 867 |
+
|
| 868 |
# -------------------------------
|
| 869 |
# Footer
|
| 870 |
# -------------------------------
|