File size: 3,877 Bytes
1d12e97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import streamlit as st
import pandas as pd
from rdflib import Graph, Namespace
import os

# Page Config
st.set_page_config(page_title="Cars Knowledge Graph Demo", layout="wide")

# Load Graph
@st.cache_resource
def load_graph():
    g = Graph()
    graph_path = "cars_knowledge_graph.ttl"
    if os.path.exists(graph_path):
        g.parse(graph_path, format="turtle")
    return g

try:
    g = load_graph()
except Exception as e:
    st.error(f"Failed to load graph: {e}")
    st.stop()

if len(g) == 0:
    st.warning("Graph is empty or not found. Please run 'src/convert_data.py' first.")
    st.stop()

# Namespaces
EX = Namespace("http://example.org/cars/")

# Sidebar Filters
st.sidebar.header("Filter Cars")

# 1. Manufacturer Filter
manu_query = """
    PREFIX ex: <http://example.org/cars/>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    SELECT DISTINCT ?name WHERE { 
        ?m a ex:Manufacturer ; rdfs:label ?name . 
    } ORDER BY ?name
"""
manufacturers = ["All"] + [str(row.name) for row in g.query(manu_query)]
selected_manu = st.sidebar.selectbox("Manufacturer", manufacturers)

# 2. Price Range
price_query = """
    PREFIX ex: <http://example.org/cars/>
    SELECT (MIN(?p) as ?min) (MAX(?p) as ?max) WHERE { ?s ex:hasPriceValue ?p }
"""
price_res = list(g.query(price_query))[0]
min_price, max_price = float(price_res.min), float(price_res.max)
selected_price = st.sidebar.slider("Max Price (USD)", min_price, max_price, max_price)

# 3. Min Horsepower
hp_query = """
    PREFIX ex: <http://example.org/cars/>
    SELECT (MIN(?hp) as ?min) (MAX(?hp) as ?max) WHERE { ?s ex:hasHorsePowerValue ?hp }
"""
hp_res = list(g.query(hp_query))[0]
min_hp, max_hp = int(hp_res.min), int(hp_res.max)
selected_hp = st.sidebar.slider("Min Horsepower", min_hp, max_hp, min_hp)

# Main Area
st.title("πŸš— Cars Knowledge Graph Explorer")
st.markdown("This application queries the RDF Knowledge Graph directly using **SPARQL**.")

# Construct Query based on filters
sparql_query = f"""
    PREFIX ex: <http://example.org/cars/>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    
    SELECT ?carName ?manuName ?price ?hp ?topSpeed ?seats
    WHERE {{
        ?car a ex:Car ;
             rdfs:label ?carName ;
             ex:hasManufacturer ?manu ;
             ex:hasPriceValue ?price ;
             ex:hasHorsePowerValue ?hp ;
             ex:hasTopSpeedKMH ?topSpeed ;
             ex:hasSeatCount ?seats .
        
        ?manu rdfs:label ?manuName .
        
        FILTER (?price <= {selected_price})
        FILTER (?hp >= {selected_hp})
        {f'FILTER (?manuName = "{selected_manu}")' if selected_manu != "All" else ""}
    }}
    ORDER BY DESC(?price)
    LIMIT 100
"""

# Run Query
results = g.query(sparql_query)

# Display Results
data = []
for row in results:
    data.append({
        "Car Model": str(row.carName),
        "Manufacturer": str(row.manuName),
        "Price ($)": f"${float(row.price):,.2f}",
        "Horsepower": int(row.hp),
        "Top Speed (km/h)": int(row.topSpeed),
        "Seats": int(row.seats)
    })

df = pd.DataFrame(data)

col1, col2, col3 = st.columns(3)
col1.metric("Total Cars Found", len(df))
col2.metric("Graph Triples", len(g))
col3.metric("Selected Manufacturer", selected_manu)

if not df.empty:
    st.dataframe(df, use_container_width=True)
else:
    st.info("No cars match your filters.")

# Advanced: Raw SPARQL
with st.expander("Run Custom SPARQL Query"):
    custom_query = st.text_area("SPARQL Query", """
        PREFIX ex: <http://example.org/cars/>
        SELECT ?name ?price WHERE {
            ?c ex:hasPriceValue ?price ;
               rdfs:label ?name .
        } LIMIT 5
    """)
    if st.button("Run Query"):
        try:
            raw_res = g.query(custom_query)
            st.write(list(raw_res))
        except Exception as e:
            st.error(f"Error: {e}")