""" app.py HIFFI Artist Intelligence - Multi-Platform Executive Dashboard Clean dark-themed design with multi-platform evidence tiers, Spotify & Instagram telemetry, ChartMasters record sales (CSPC/EAS), breakout velocity index, and deep-dive scouting dossier. """ import io from pathlib import Path import pandas as pd import plotly.express as px import plotly.graph_objects as go 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", "chartmasters_sales_rank", "cohort_sales_rank", "pure_album_sales", "physical_singles_sales", "digital_singles_sales", "streaming_eas", "total_eas_cspc", ] 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 • Sales 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)", "💿 Record Sales & CSPC (ChartMasters)", "🔍 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("Governance: Multi-Platform Signals + Verified ChartMasters Provenance") # ----------------- 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, dynamic weight redistribution, and verified record sales.

", 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 (5 Columns) ----------------- k1, k2, k3, k4, k5 = st.columns(5) 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, ) with k5: sales_indexed = df["total_eas_cspc"].notna().sum() if "total_eas_cspc" in df.columns else 0 st.markdown( f"""
Record Sales
{sales_indexed}
ChartMasters CSPC records
""", 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" ] elif view_mode == "💿 Record Sales & CSPC (ChartMasters)": table_df = ( filtered_df[filtered_df["total_eas_cspc"].notna()] .sort_values(by="total_eas_cspc", ascending=False) .copy() if "total_eas_cspc" in filtered_df.columns else filtered_df.copy() ) cols = [ "cohort_sales_rank", "chartmasters_sales_rank", "name", "total_eas_cspc", "pure_album_sales", "streaming_eas", "physical_singles_sales", "digital_singles_sales", "sales_data_status", "sales_collected_at" ] 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", "total_eas_cspc", "sales_data_status", "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=330, 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"), "cohort_sales_rank": st.column_config.NumberColumn("Cohort #", format="#%d", width="small"), "chartmasters_sales_rank": st.column_config.NumberColumn("Global #", 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"), "total_eas_cspc": st.column_config.NumberColumn("Total EAS (CSPC)", format="%,d", width="medium"), "pure_album_sales": st.column_config.NumberColumn("Pure Albums", format="%,d", width="medium"), "streaming_eas": st.column_config.NumberColumn("Streaming EAS", format="%,d", width="medium"), "physical_singles_sales": st.column_config.NumberColumn("Physical", format="%,d", width="small"), "digital_singles_sales": st.column_config.NumberColumn("Digital", format="%,d", width="small"), "sales_data_status": st.column_config.TextColumn("Status", width="medium"), "sales_collected_at": st.column_config.TextColumn("Collected Date", width="medium"), "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 & Format Analysis ----------------- st.markdown("#### 📊 Commercial & Multi-Platform Analytics") if view_mode == "💿 Record Sales & CSPC (ChartMasters)": c_sales1, c_sales2 = st.columns(2) with c_sales1: top_sales = ( filtered_df[filtered_df["total_eas_cspc"].notna()] .sort_values(by="total_eas_cspc", ascending=False) .head(15) ) if not top_sales.empty: fig_format = go.Figure() fig_format.add_trace(go.Bar( name="Pure Albums", x=top_sales["name"], y=top_sales["pure_album_sales"], marker_color="#8b5cf6" )) fig_format.add_trace(go.Bar( name="Digital Singles", x=top_sales["name"], y=top_sales["digital_singles_sales"], marker_color="#38bdf8" )) fig_format.add_trace(go.Bar( name="Streaming EAS", x=top_sales["name"], y=top_sales["streaming_eas"], marker_color="#10b981" )) fig_format.update_layout( barmode="stack", title=dict( text="Format Breakdown: Pure Albums vs Singles vs Streaming (Top 15)", font=dict(size=14), ), template="plotly_dark", paper_bgcolor="#111827", plot_bgcolor="#111827", font=dict(color="#9ca3af"), margin=dict(l=20, r=20, t=60, b=20), height=350, legend=dict( orientation="h", yanchor="bottom", y=1.04, xanchor="right", x=1.0, font=dict(size=11), ), ) st.plotly_chart(fig_format, width="stretch") else: st.info("No sales data available for current filter selection.") with c_sales2: sales_scatter = filtered_df.dropna(subset=["pure_album_sales", "streaming_eas"]).copy() if not sales_scatter.empty: fig_scatter_sales = px.scatter( sales_scatter, x="pure_album_sales", y="streaming_eas", size="total_eas_cspc", hover_name="name", color="total_eas_cspc", color_continuous_scale="Viridis", log_x=True, log_y=True, title="Commercial Shift: Pure Album Sales vs Streaming Conversions", labels={ "pure_album_sales": "Pure Album Sales (Log Scale)", "streaming_eas": "Streaming Equivalent Sales (Log Scale)", "total_eas_cspc": "Total EAS" }, template="plotly_dark", ) fig_scatter_sales.update_layout( paper_bgcolor="#111827", plot_bgcolor="#111827", font=dict(color="#9ca3af"), margin=dict(l=20, r=20, t=40, b=20), height=350, ) st.plotly_chart(fig_scatter_sales, width="stretch") else: st.info("Insufficient records with both pure sales and streaming figures.") else: 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, d5 = st.columns(5) 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)") with d5: sales_val = row.get("total_eas_cspc") st.metric("Total EAS Sales", f"{int(sales_val):,}" if pd.notna(sales_val) else "Uncataloged (NaN)") st.markdown( f"""
Artist: {row['name']}
Evidence Tier: Tier {int(row.get('platform_evidence_tier', 1))}
Global Sales Rank: {f"#{int(row.get('chartmasters_sales_rank'))}" if pd.notna(row.get('chartmasters_sales_rank')) else "Unranked"}
Cohort Sales Rank: {f"#{int(row.get('cohort_sales_rank'))}" if pd.notna(row.get('cohort_sales_rank')) else "Uncataloged"}
Pure Albums: {f"{int(row.get('pure_album_sales')):,}" if pd.notna(row.get('pure_album_sales')) else "N/A"}
Streaming EAS: {f"{int(row.get('streaming_eas')):,}" if pd.notna(row.get('streaming_eas')) else "N/A"}
Sales Status: {row.get('sales_data_status', 'NOT_CATALOGED_YET')}
Provenance: ChartMasters Verification
Effective Weights: {row.get('effective_weights', 'N/A')}
Anomaly Flags: {row.get('anomaly_flags', 'CLEAN')}
""", unsafe_allow_html=True, )