refactor: simplify Explorer to 3 focused tabs — compass, trajectories, SVD
Removes embedding-heavy search and generic browser tabs from the Explorer. The project does not currently use embeddings meaningfully, so the similarity search and browser features were dead weight. Changes: - explorer.py: Remove search and browser tabs, keep compass/trajectories/SVD - explorer.py: Remove fused_embeddings and similarity_cache stats from sidebar - Home.py: Update Explorer description to match new focused layout - analysis/tabs/__init__.py: Remove search and browser exports - tests: Update decomposition and import tests for new tab set Result: Explorer now has 3 focused analytical tabs instead of 5.
This commit is contained in:
@@ -19,8 +19,8 @@ def main() -> None:
|
|||||||
st.markdown(
|
st.markdown(
|
||||||
"**Motief** brengt de Nederlandse Tweede Kamer in kaart op basis van "
|
"**Motief** brengt de Nederlandse Tweede Kamer in kaart op basis van "
|
||||||
"echte stemmingen over moties. Gebruik de Stemwijzer om te ontdekken welke "
|
"echte stemmingen over moties. Gebruik de Stemwijzer om te ontdekken welke "
|
||||||
"partij het beste bij jouw standpunten past, of verken de politieke ruimte "
|
"partij het beste bij jouw standpunten past, of verken het politieke landschap "
|
||||||
"zelf in de Explorer."
|
"in de Explorer: kompas, trajecten en SVD-analyse."
|
||||||
)
|
)
|
||||||
|
|
||||||
st.divider()
|
st.divider()
|
||||||
@@ -39,7 +39,7 @@ def main() -> None:
|
|||||||
st.subheader("🔭 Politiek Explorer")
|
st.subheader("🔭 Politiek Explorer")
|
||||||
st.markdown(
|
st.markdown(
|
||||||
"Verken het politieke kompas, partijtrajecten door de tijd, "
|
"Verken het politieke kompas, partijtrajecten door de tijd, "
|
||||||
"en zoek vergelijkbare moties op in het archief."
|
"en de onderliggende SVD-componenten die de assen vormen."
|
||||||
)
|
)
|
||||||
st.page_link("pages/2_Explorer.py", label="Open Explorer", icon="🔭")
|
st.page_link("pages/2_Explorer.py", label="Open Explorer", icon="🔭")
|
||||||
|
|
||||||
|
|||||||
@@ -6,16 +6,12 @@ Each module contains a `build_<tab>_tab()` function that implements one tab.
|
|||||||
|
|
||||||
from analysis.tabs.compass import build_compass_tab
|
from analysis.tabs.compass import build_compass_tab
|
||||||
from analysis.tabs.trajectories import build_trajectories_tab
|
from analysis.tabs.trajectories import build_trajectories_tab
|
||||||
from analysis.tabs.search import build_search_tab
|
|
||||||
from analysis.tabs.browser import build_browser_tab
|
|
||||||
from analysis.tabs.components import build_svd_components_tab
|
from analysis.tabs.components import build_svd_components_tab
|
||||||
from analysis.tabs.quiz import build_mp_quiz_tab
|
from analysis.tabs.quiz import build_mp_quiz_tab
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"build_compass_tab",
|
"build_compass_tab",
|
||||||
"build_trajectories_tab",
|
"build_trajectories_tab",
|
||||||
"build_search_tab",
|
|
||||||
"build_browser_tab",
|
|
||||||
"build_svd_components_tab",
|
"build_svd_components_tab",
|
||||||
"build_mp_quiz_tab",
|
"build_mp_quiz_tab",
|
||||||
]
|
]
|
||||||
|
|||||||
+5
-67
@@ -1,10 +1,9 @@
|
|||||||
"""Parlement Explorer — Streamlit data analysis app.
|
"""Parlement Explorer — Streamlit data analysis app.
|
||||||
|
|
||||||
Four tabs:
|
Three tabs:
|
||||||
1. Politiek Kompas — 2D scatter of MPs/parties, window slider
|
1. Politiek Kompas — 2D scatter of MPs/parties, window slider
|
||||||
2. Partij Trajectories — party centroid lines over time
|
2. Partij Trajectories — party centroid lines over time
|
||||||
3. Motie Zoeken — text search + similarity lookup
|
3. SVD Components — component themes, scree plot, party positions
|
||||||
4. Motie Browser — sortable table + detail panel
|
|
||||||
|
|
||||||
Run with: streamlit run explorer.py
|
Run with: streamlit run explorer.py
|
||||||
|
|
||||||
@@ -408,49 +407,6 @@ def load_motions_df(db_path: str) -> pd.DataFrame:
|
|||||||
return explorer_data.load_motions_df(db_path)
|
return explorer_data.load_motions_df(db_path)
|
||||||
|
|
||||||
|
|
||||||
def query_similar(
|
|
||||||
db_path: str,
|
|
||||||
source_motion_id: int,
|
|
||||||
vector_type: str = "fused",
|
|
||||||
top_k: int = 10,
|
|
||||||
) -> pd.DataFrame:
|
|
||||||
"""Return top-k similar motions from similarity_cache (read-only)."""
|
|
||||||
return explorer_data.query_similar(db_path, source_motion_id, vector_type, top_k)
|
|
||||||
|
|
||||||
|
|
||||||
def _window_to_dates(window_id: str) -> tuple[str, str]:
|
|
||||||
"""Return (start_date, end_date) ISO strings for a given window_id."""
|
|
||||||
return trajectory.window_to_dates(window_id)
|
|
||||||
|
|
||||||
|
|
||||||
def build_compass_tab(*args, **kwargs):
|
|
||||||
"""Build the Politiek Kompas tab."""
|
|
||||||
from analysis.tabs.compass import build_compass_tab as _impl
|
|
||||||
|
|
||||||
return _impl(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def build_trajectories_tab(*args, **kwargs):
|
|
||||||
"""Build the Partij Trajectories tab."""
|
|
||||||
from analysis.tabs.trajectories import build_trajectories_tab as _impl
|
|
||||||
|
|
||||||
return _impl(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def build_search_tab(*args, **kwargs):
|
|
||||||
"""Build the Motie Zoeken tab."""
|
|
||||||
from analysis.tabs.search import build_search_tab as _impl
|
|
||||||
|
|
||||||
return _impl(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def build_browser_tab(*args, **kwargs):
|
|
||||||
"""Build the Motie Browser tab."""
|
|
||||||
from analysis.tabs.browser import build_browser_tab as _impl
|
|
||||||
|
|
||||||
return _impl(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def build_svd_components_tab(*args, **kwargs):
|
def build_svd_components_tab(*args, **kwargs):
|
||||||
"""Build the SVD Components tab."""
|
"""Build the SVD Components tab."""
|
||||||
from analysis.tabs.components import build_svd_components_tab as _impl
|
from analysis.tabs.components import build_svd_components_tab as _impl
|
||||||
@@ -476,24 +432,16 @@ def run_app() -> None:
|
|||||||
st.sidebar.title("Instellingen")
|
st.sidebar.title("Instellingen")
|
||||||
db_path = "data/motions.db"
|
db_path = "data/motions.db"
|
||||||
window_size = "annual"
|
window_size = "annual"
|
||||||
show_rejected = st.sidebar.checkbox("Toon verworpen moties", value=False)
|
|
||||||
|
|
||||||
with st.sidebar.expander("ℹ️ Over", expanded=False):
|
with st.sidebar.expander("ℹ️ Over", expanded=False):
|
||||||
try:
|
try:
|
||||||
if _DUCKDB_AVAILABLE:
|
if _DUCKDB_AVAILABLE:
|
||||||
con = duckdb.connect(database=db_path, read_only=True)
|
con = duckdb.connect(database=db_path, read_only=True)
|
||||||
n_motions = con.execute("SELECT COUNT(*) FROM motions").fetchone()[0]
|
n_motions = con.execute("SELECT COUNT(*) FROM motions").fetchone()[0]
|
||||||
n_fused = con.execute(
|
|
||||||
"SELECT COUNT(*) FROM fused_embeddings"
|
|
||||||
).fetchone()[0]
|
|
||||||
n_sim = con.execute("SELECT COUNT(*) FROM similarity_cache").fetchone()[
|
|
||||||
0
|
|
||||||
]
|
|
||||||
con.close()
|
con.close()
|
||||||
st.markdown(
|
st.markdown(
|
||||||
f"**Moties:** {n_motions:,} \n"
|
f"**Moties:** {n_motions:,} \n"
|
||||||
f"**Fused embeddings:** {n_fused:,} \n"
|
f"**Vensters:** per jaar + huidig parlement"
|
||||||
f"**Similarity cache:** {n_sim:,}"
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
st.warning(
|
st.warning(
|
||||||
@@ -505,22 +453,16 @@ def run_app() -> None:
|
|||||||
tab_labels = [
|
tab_labels = [
|
||||||
"🧭 Politiek Kompas",
|
"🧭 Politiek Kompas",
|
||||||
"📈 Trajectories",
|
"📈 Trajectories",
|
||||||
"🔍 Motie Zoeken",
|
|
||||||
"📋 Motie Browser",
|
|
||||||
"🔬 SVD Components",
|
"🔬 SVD Components",
|
||||||
]
|
]
|
||||||
|
|
||||||
if hasattr(st, "tabs") and callable(getattr(st, "tabs")):
|
if hasattr(st, "tabs") and callable(getattr(st, "tabs")):
|
||||||
tab1, tab2, tab3, tab4, tab5 = st.tabs(tab_labels)
|
tab1, tab2, tab3 = st.tabs(tab_labels)
|
||||||
with tab1:
|
with tab1:
|
||||||
build_compass_tab(db_path, window_size)
|
build_compass_tab(db_path, window_size)
|
||||||
with tab2:
|
with tab2:
|
||||||
build_trajectories_tab(db_path, window_size)
|
build_trajectories_tab(db_path, window_size)
|
||||||
with tab3:
|
with tab3:
|
||||||
build_search_tab(db_path, show_rejected)
|
|
||||||
with tab4:
|
|
||||||
build_browser_tab(db_path, show_rejected)
|
|
||||||
with tab5:
|
|
||||||
build_svd_components_tab(db_path)
|
build_svd_components_tab(db_path)
|
||||||
else:
|
else:
|
||||||
selection = st.radio("Tab", tab_labels)
|
selection = st.radio("Tab", tab_labels)
|
||||||
@@ -528,10 +470,6 @@ def run_app() -> None:
|
|||||||
build_compass_tab(db_path, window_size)
|
build_compass_tab(db_path, window_size)
|
||||||
elif selection == tab_labels[1]:
|
elif selection == tab_labels[1]:
|
||||||
build_trajectories_tab(db_path, window_size)
|
build_trajectories_tab(db_path, window_size)
|
||||||
elif selection == tab_labels[2]:
|
|
||||||
build_search_tab(db_path, show_rejected)
|
|
||||||
elif selection == tab_labels[3]:
|
|
||||||
build_browser_tab(db_path, show_rejected)
|
|
||||||
else:
|
else:
|
||||||
build_svd_components_tab(db_path)
|
build_svd_components_tab(db_path)
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ class TestExplorerDecomposition:
|
|||||||
tabs = [
|
tabs = [
|
||||||
("analysis/tabs/compass.py", "build_compass_tab"),
|
("analysis/tabs/compass.py", "build_compass_tab"),
|
||||||
("analysis/tabs/trajectories.py", "build_trajectories_tab"),
|
("analysis/tabs/trajectories.py", "build_trajectories_tab"),
|
||||||
("analysis/tabs/search.py", "build_search_tab"),
|
|
||||||
("analysis/tabs/browser.py", "build_browser_tab"),
|
|
||||||
("analysis/tabs/components.py", "build_svd_components_tab"),
|
("analysis/tabs/components.py", "build_svd_components_tab"),
|
||||||
("analysis/tabs/quiz.py", "build_mp_quiz_tab"),
|
("analysis/tabs/quiz.py", "build_mp_quiz_tab"),
|
||||||
]
|
]
|
||||||
@@ -75,8 +73,6 @@ class TestExplorerDecomposition:
|
|||||||
tab_modules = [
|
tab_modules = [
|
||||||
"analysis/tabs/compass.py",
|
"analysis/tabs/compass.py",
|
||||||
"analysis/tabs/trajectories.py",
|
"analysis/tabs/trajectories.py",
|
||||||
"analysis/tabs/search.py",
|
|
||||||
"analysis/tabs/browser.py",
|
|
||||||
"analysis/tabs/components.py",
|
"analysis/tabs/components.py",
|
||||||
"analysis/tabs/quiz.py",
|
"analysis/tabs/quiz.py",
|
||||||
"analysis/tabs/_rendering.py",
|
"analysis/tabs/_rendering.py",
|
||||||
|
|||||||
@@ -9,6 +9,5 @@ def test_explorer_importable():
|
|||||||
assert callable(mod.run_app)
|
assert callable(mod.run_app)
|
||||||
assert hasattr(mod, "load_positions")
|
assert hasattr(mod, "load_positions")
|
||||||
assert hasattr(mod, "load_motions_df")
|
assert hasattr(mod, "load_motions_df")
|
||||||
assert hasattr(mod, "query_similar")
|
assert hasattr(mod, "build_svd_components_tab")
|
||||||
assert hasattr(mod, "build_compass_tab")
|
assert hasattr(mod, "build_mp_quiz_tab")
|
||||||
assert hasattr(mod, "build_search_tab")
|
|
||||||
|
|||||||
Reference in New Issue
Block a user