""" app.py HIFFI Artist Intelligence - Multi-Platform Executive Dashboard Clean dark-themed design with multi-platform evidence tiers, Spotify & Instagram telemetry, breakout velocity index, and deep-dive scouting dossier. """ import io from pathlib import Path import pandas as pd import plotly.express as px import streamlit as st st.set_page_config( page_title="HIFFI | Multi-Platform Intelligence", page_icon="⚡", layout="wide", initial_sidebar_state="expanded", ) DATA_PATH = Path("data/hiffi_multiplatform_500.csv") FALLBACK_DATA_PATH = Path("enriched_artists.csv") # Global CSS Polish st.markdown( """ """, unsafe_allow_html=True, ) @st.cache_data(ttl=60) def load_data(): target = DATA_PATH if DATA_PATH.exists() else FALLBACK_DATA_PATH if not target.exists(): return pd.DataFrame() df = pd.read_csv(target) # Normalize primary score & rank columns if running from legacy source if "hiffi_xp_published_rank" not in df.columns: df["hiffi_xp_published_rank"] = df.get("hiffi_xp_rank", df.get("hiffi_rank", df.index + 1)) if "hiffi_xp_score" not in df.columns: df["hiffi_xp_score"] = df.get("production_hiffi_score", df.get("hiffi_score", 0.0)) if "platform_evidence_tier" not in df.columns: has_yt = df.get("production_hiffi_score", df.get("hiffi_score")).notna().astype(int) has_sp = df.get("spotify_monthly_listeners", pd.Series(index=df.index)).notna().astype(int) has_ig = df.get("instagram_followers", pd.Series(index=df.index)).notna().astype(int) df["platform_evidence_tier"] = has_yt + has_sp + has_ig numeric_cols = [ "hiffi_xp_published_rank", "hiffi_xp_rank", "hiffi_xp_score", "production_hiffi_rank", "production_hiffi_score", "platform_evidence_tier", "breakout_velocity_index", "subscriber_count", "daily_view_velocity", "momentum_30d", "spotify_monthly_listeners", "spotify_daily_change", "instagram_followers", "confidence_score", "breakout_rank" ] for col in numeric_cols: if col in df.columns: df[col] = pd.to_numeric(df[col], errors="coerce") if "subgenre" not in df.columns: def infer_subgenre(r): subs = r.get("subscriber_count", 0) or 0 bvi = r.get("breakout_velocity_index", 0) or 0 if bvi >= 70: return "Breakout / Emerging" elif subs >= 15000000: return "Legends" else: return "Trap & Street" df["subgenre"] = df.apply(infer_subgenre, axis=1) return df def to_excel_bytes(dataframe: pd.DataFrame) -> bytes: output = io.BytesIO() with pd.ExcelWriter(output, engine="openpyxl") as writer: dataframe.to_excel(writer, index=False, sheet_name="HIFFI_Cohort") return output.getvalue() df = load_data() # ----------------- Sidebar Controls ----------------- with st.sidebar: st.markdown("### ⚡ HIFFI Multi-Platform") st.caption("YouTube • Spotify • Instagram Analytics") st.markdown("
", unsafe_allow_html=True) if df.empty: st.error("No dataset found. Run 'python run_pipeline.py' to generate master data.") st.stop() view_mode = st.radio( "Leaderboard Perspective:", ["🏆 Published Multi-Platform Rank", "🚀 Breakout Velocity (BVI)", "🔍 Full Cohort Audit Grid"], index=0, ) st.markdown("
", unsafe_allow_html=True) st.markdown("##### 🛡️ Cohort Filters") all_verticals = sorted(df["subgenre"].dropna().unique().tolist()) selected_verticals = st.multiselect("Vertical", options=all_verticals, default=all_verticals) tier_options = sorted(df["platform_evidence_tier"].dropna().unique().astype(int).tolist(), reverse=True) selected_tiers = st.multiselect("Evidence Tier", options=tier_options, default=tier_options) min_xp = st.slider("Min HIFFI-XP Score", 0.0, 100.0, 0.0, 5.0) filtered_df = df[ (df["subgenre"].isin(selected_verticals)) & (df["platform_evidence_tier"].isin(selected_tiers)) & (df["hiffi_xp_score"].fillna(0.0) >= min_xp) ].copy() with st.sidebar: st.markdown("
", unsafe_allow_html=True) st.markdown("##### 💾 Export Filtered Cohort") col_csv, col_xlsx = st.columns(2) csv_payload = filtered_df.to_csv(index=False).encode("utf-8") col_csv.download_button( "📥 CSV", data=csv_payload, file_name="hiffi_multiplatform_filtered.csv", mime="text/csv", width="stretch", ) excel_payload = to_excel_bytes(filtered_df) col_xlsx.download_button( "📊 Excel", data=excel_payload, file_name="hiffi_multiplatform_filtered.xlsx", mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", width="stretch", ) st.markdown("
", unsafe_allow_html=True) st.caption("Weights: YouTube (50%) • Spotify (30%) • Instagram (20%)") # ----------------- Main Header ----------------- head_col1, head_col2 = st.columns([3, 1]) with head_col1: st.markdown("

HIFFI Multi-Platform Intelligence Hub

", unsafe_allow_html=True) st.markdown("

Multi-platform composite rankings with zero-imputation policy and dynamic weight redistribution.

", unsafe_allow_html=True) with head_col2: st.markdown( f"
Filtered Cohort: {len(filtered_df)} / {len(df)} artists
", unsafe_allow_html=True, ) # ----------------- KPI Cards Row ----------------- k1, k2, k3, k4 = st.columns(4) with k1: st.markdown( f"""
Tracked Artists
{len(df)}
Monitored Cohort
""", unsafe_allow_html=True, ) with k2: t3_count = len(df[df["platform_evidence_tier"] == 3]) st.markdown( f"""
Tier 3 (Complete)
{t3_count}
YouTube + Spotify + Instagram
""", unsafe_allow_html=True, ) with k3: sp_count = df["spotify_monthly_listeners"].notna().sum() st.markdown( f"""
Spotify Telemetry
{sp_count}
Verified monthly listeners
""", unsafe_allow_html=True, ) with k4: ig_count = df["instagram_followers"].notna().sum() st.markdown( f"""
Instagram Audience
{ig_count}
Verified public followings
""", unsafe_allow_html=True, ) st.markdown("
", unsafe_allow_html=True) # ----------------- Podium ----------------- top3 = filtered_df.sort_values(by="hiffi_xp_published_rank", ascending=True).head(3) if len(top3) >= 3: st.markdown("#### 👑 Market Leaders (Published Rankings)") p1, p2, p3 = st.columns(3) podium_data = [ (p1, top3.iloc[0], "🥇 PUBLISHED #1", "podium-gold", "#f59e0b"), (p2, top3.iloc[1], "🥈 PUBLISHED #2", "podium-silver", "#94a3b8"), (p3, top3.iloc[2], "🥉 PUBLISHED #3", "podium-bronze", "#f97316"), ] for col, row_data, rank_label, css_class, accent_color in podium_data: tier_val = int(row_data.get("platform_evidence_tier", 1)) badge_cls = f"badge-tier{tier_val}" sp_str = f"{int(row_data['spotify_monthly_listeners']):,}" if pd.notna(row_data.get("spotify_monthly_listeners")) else "NaN" ig_str = f"{int(row_data['instagram_followers']):,}" if pd.notna(row_data.get("instagram_followers")) else "NaN" with col: st.markdown( f"""
{rank_label} Tier {tier_val} Evidence
{row_data['name']}
{row_data.get('channel_title', '')}
HIFFI-XP
{row_data['hiffi_xp_score']:.2f}
Spotify Monthly
{sp_str}
IG Followers
{ig_str}
""", unsafe_allow_html=True, ) st.markdown("
", unsafe_allow_html=True) # ----------------- Leaderboard Grid ----------------- st.markdown(f"#### 📋 {view_mode}") if view_mode == "🏆 Published Multi-Platform Rank": table_df = filtered_df.sort_values(by="hiffi_xp_published_rank", ascending=True).copy() cols = [ "hiffi_xp_published_rank", "hiffi_xp_rank", "name", "platform_evidence_tier", "hiffi_xp_score", "spotify_monthly_listeners", "instagram_followers", "effective_weights", "anomaly_flags" ] elif view_mode == "🚀 Breakout Velocity (BVI)": table_df = ( filtered_df[filtered_df["breakout_velocity_index"].notna()] .sort_values(by="breakout_velocity_index", ascending=False) .copy() ) cols = [ "name", "breakout_velocity_index", "hiffi_xp_published_rank", "daily_view_velocity", "momentum_30d", "subscriber_count", "subgenre" ] else: table_df = filtered_df.sort_values(by="hiffi_xp_published_rank", ascending=True).copy() cols = [ "hiffi_xp_published_rank", "name", "production_hiffi_rank", "hiffi_xp_rank", "rank_delta", "platform_evidence_tier", "hiffi_xp_score", "spotify_monthly_listeners", "instagram_followers", "evidence_exclusions", "anomaly_flags" ] render_cols = [c for c in cols if c in table_df.columns] st.dataframe( table_df[render_cols].reset_index(drop=True), width="stretch", height=320, column_config={ "hiffi_xp_published_rank": st.column_config.NumberColumn("Pub Rank", format="%d", width="small"), "hiffi_xp_rank": st.column_config.NumberColumn("Raw XP Rank", format="%d", width="small"), "production_hiffi_rank": st.column_config.NumberColumn("YT Rank", format="%d", width="small"), "platform_evidence_tier": st.column_config.NumberColumn("Tier", format="%d", width="small"), "name": st.column_config.TextColumn("Artist", width="medium"), "hiffi_xp_score": st.column_config.ProgressColumn("HIFFI-XP Score", format="%.2f", min_value=0, max_value=100, width="medium"), "breakout_velocity_index": st.column_config.ProgressColumn("BVI", format="%.1f", min_value=0, max_value=100, width="small"), "spotify_monthly_listeners": st.column_config.NumberColumn("Spotify Monthly", format="%,d", width="medium"), "instagram_followers": st.column_config.NumberColumn("IG Followers", format="%,d", width="medium"), "effective_weights": st.column_config.TextColumn("Dynamic Redistribution", width="large"), "anomaly_flags": st.column_config.TextColumn("Anomaly Status", width="medium"), "evidence_exclusions": st.column_config.TextColumn("Exclusions", width="large"), }, ) st.markdown("
", unsafe_allow_html=True) # ----------------- Visual Insights Charts ----------------- st.markdown("#### 📊 Multi-Platform Analytics") c_left, c_right = st.columns(2) with c_left: chart_df = filtered_df.dropna(subset=["spotify_monthly_listeners", "instagram_followers", "hiffi_xp_score"]).copy() if not chart_df.empty: fig_scatter = px.scatter( chart_df, x="spotify_monthly_listeners", y="instagram_followers", size="hiffi_xp_score", color="platform_evidence_tier", hover_name="name", log_x=True, log_y=True, title="Spotify Monthly Listeners vs. Instagram Followers", labels={ "spotify_monthly_listeners": "Spotify Monthly Listeners (Log Scale)", "instagram_followers": "Instagram Followers (Log Scale)", "platform_evidence_tier": "Tier", }, template="plotly_dark", ) fig_scatter.update_layout( paper_bgcolor="#111827", plot_bgcolor="#111827", font=dict(color="#9ca3af"), margin=dict(l=20, r=20, t=40, b=20), height=320, ) st.plotly_chart(fig_scatter, width="stretch") else: st.info("Insufficient complete data points to render multi-platform scatter plot.") with c_right: tier_counts = filtered_df["platform_evidence_tier"].value_counts().reset_index() tier_counts.columns = ["Tier", "Count"] fig_pie = px.pie( tier_counts, values="Count", names="Tier", title="Evidence Tier Cohort Distribution", template="plotly_dark", color="Tier", color_discrete_map={3: "#10b981", 2: "#38bdf8", 1: "#f59e0b", 0: "#ef4444"} ) fig_pie.update_layout( paper_bgcolor="#111827", plot_bgcolor="#111827", font=dict(color="#9ca3af"), margin=dict(l=20, r=20, t=40, b=20), height=320, ) st.plotly_chart(fig_pie, width="stretch") # ----------------- Deep Dive Scouting Dossier ----------------- st.markdown("
", unsafe_allow_html=True) st.markdown("#### 🔎 Artist Dossier") selected_name = st.selectbox("Inspect Artist Details:", df["name"].unique(), label_visibility="collapsed") row = df[df["name"] == selected_name].iloc[0] d1, d2, d3, d4 = st.columns(4) with d1: h_val = row.get("hiffi_xp_score") st.metric("HIFFI-XP Score", f"{h_val:.2f}" if pd.notna(h_val) else "N/A") with d2: pub_rank = row.get("hiffi_xp_published_rank") st.metric("Published Rank", f"#{int(pub_rank)}" if pd.notna(pub_rank) else "Unranked") with d3: sp_l = row.get("spotify_monthly_listeners") st.metric("Spotify Listeners", f"{int(sp_l):,}" if pd.notna(sp_l) else "Unindexed (NaN)") with d4: ig_f = row.get("instagram_followers") st.metric("Instagram Followers", f"{int(ig_f):,}" if pd.notna(ig_f) else "Unindexed (NaN)") st.markdown( f"""
Artist: {row['name']}
Evidence Tier: Tier {int(row.get('platform_evidence_tier', 1))}
Instagram Status: {row.get('instagram_verification_status', 'N/A')}
Spotify Source: {row.get('spotify_data_source', 'N/A')}
Effective Weights: {row.get('effective_weights', 'N/A')}
Anomaly Flags: {row.get('anomaly_flags', 'CLEAN')}
""", unsafe_allow_html=True, )