Files
hiffi-artist-intelligence/app.py
T

711 lines
39 KiB
Python
Raw Normal View History

"""
app.py
HIFFI Artist Intelligence - Multi-Platform Executive Dashboard
Dual-Engine Architecture:
1. HIFFI Hip-Hop 500: Multi-platform evidence tiers, YouTube/Spotify/IG telemetry, BVI, CPI engine.
2. Global Master Catalog (17k): Empirical registry verification (CSPC, RIAA, Last.fm) with ordinal tier ranking.
"""
from pathlib import Path
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import streamlit as st
try:
from core.cpi_engine import CommercialPowerEngine
except ImportError:
CommercialPowerEngine = None
try:
from exporters.excel_workbook import generate_executive_sales_workbook
except ImportError:
generate_executive_sales_workbook = None
st.set_page_config(
page_title="HIFFI | Multi-Platform Intelligence",
page_icon="⚡",
layout="wide",
initial_sidebar_state="expanded",
)
PATH_500 = Path("data/hiffi_multiplatform_500.csv")
PATH_17K = Path("data/master_artists_intelligence_17k_final.csv")
FALLBACK_PATH = Path("enriched_artists.csv")
# Global CSS Styling
st.markdown(
"""
<style>
.block-container {
padding-top: 1.8rem;
padding-bottom: 2.5rem;
padding-left: 2.5rem;
padding-right: 2.5rem;
max-width: 100% !important;
}
.kpi-box {
background: #111827;
border: 1px solid #1f2937;
border-radius: 12px;
padding: 16px 20px;
margin-bottom: 12px;
}
.kpi-title {
font-size: 0.75rem;
font-weight: 700;
color: #9ca3af;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.kpi-value {
font-size: 1.9rem;
font-weight: 800;
color: #f9fafb;
margin: 4px 0;
}
.kpi-subtitle {
font-size: 0.75rem;
color: #6b7280;
}
.coverage-card {
background: #0f172a;
border: 1px solid #1e293b;
border-radius: 8px;
padding: 12px 18px;
margin-bottom: 16px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
}
.sim-kpi-card {
background: #0f172a;
border: 1px solid #334155;
border-radius: 8px;
padding: 10px 14px;
margin-bottom: 10px;
}
.sim-kpi-title {
font-size: 0.68rem;
font-weight: 700;
color: #94a3b8;
text-transform: uppercase;
}
.sim-kpi-val {
font-size: 1.25rem;
font-weight: 800;
margin-top: 2px;
}
.podium-tile {
background: #111827;
border-radius: 12px;
padding: 18px 20px;
border: 1px solid #1f2937;
height: 100%;
}
.podium-gold { border-top: 4px solid #f59e0b; }
.podium-silver { border-top: 4px solid #94a3b8; }
.podium-bronze { border-top: 4px solid #f97316; }
.badge {
display: inline-block;
padding: 3px 8px;
border-radius: 6px;
font-size: 0.70rem;
font-weight: 700;
text-transform: uppercase;
}
.badge-tier3 { background: rgba(16, 185, 129, 0.2); color: #10b981; }
.badge-tier2 { background: rgba(56, 189, 248, 0.2); color: #38bdf8; }
.badge-tier1 { background: rgba(245, 158, 11, 0.2); color: #f59e0b; }
.badge-dormant { background: rgba(239, 68, 68, 0.2); color: #ef4444; }
.custom-divider {
height: 1px;
background: #1f2937;
margin: 24px 0;
}
</style>
""",
unsafe_allow_html=True,
)
@st.cache_data(ttl=60)
def load_hiffi_500():
target = PATH_500 if PATH_500.exists() else FALLBACK_PATH
if not target.exists():
return pd.DataFrame()
df = pd.read_csv(target)
if "name" not in df.columns and "artist_name" in df.columns:
df["name"] = df["artist_name"]
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",
"riaa_certified_album_units", "riaa_certified_singles_units"
]
for col in numeric_cols:
if col in df.columns:
df[col] = pd.to_numeric(df[col], errors="coerce")
if CommercialPowerEngine is not None:
try:
eng = CommercialPowerEngine()
df["commercial_power_index"] = eng.calculate_cpi(df)
except Exception:
df["commercial_power_index"] = None
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
@st.cache_data(ttl=60)
def load_master_17k():
if not PATH_17K.exists():
return pd.DataFrame()
df = pd.read_csv(PATH_17K)
if "name" not in df.columns and "artist_name" in df.columns:
df["name"] = df["artist_name"]
return df
df_500 = load_hiffi_500()
df_17k = load_master_17k()
engine = CommercialPowerEngine() if CommercialPowerEngine is not None else None
def get_provenance_badge(status: str) -> str:
s = str(status).strip()
if "CSPC" in s or s == "VERIFIED_CSPC":
return "✅ VERIFIED (CSPC)"
elif "RIAA" in s or "COMMERCIAL_CORE" in s:
return "🏅 VERIFIED (RIAA)"
elif "LASTFM" in s:
return "📻 VERIFIED (Last.fm)"
elif "ESTIMATED_SEA" in s:
return "📊 ESTIMATED (SEA)"
return "⏳ UNAUDITED / PENDING"
# ----------------- Sidebar Controls -----------------
with st.sidebar:
st.markdown("### ⚡ HIFFI Intelligence Suite")
st.caption("Hip-Hop 500 & Master Catalog Intelligence")
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
# Dataset Mode Switcher
catalog_source = st.selectbox(
"🗂️ Active Data Scope:",
["⚡ Hip-Hop 500 (Executive Telemetry)", "🌐 Global Master Catalog (17,000+ Acts)"],
index=0
)
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
# =====================================================================
# MODULE 1: GLOBAL MASTER CATALOG (17,000+ ACTS)
# =====================================================================
if "Global Master Catalog" in catalog_source:
with st.sidebar:
st.markdown("##### 🔍 17k Catalog Filters")
if df_17k.empty:
st.error("Master 17k dataset not found at data/master_artists_intelligence_17k_final.csv")
st.stop()
tier_list = ["All Tiers"] + sorted(df_17k["catalog_intelligence_tier"].dropna().unique().tolist())
sel_tier = st.selectbox("Intelligence Tier:", tier_list, index=0)
search_17k = st.text_input("Search Artist Name:", placeholder="e.g. Eminem, The Roots...")
filt_17k = df_17k.copy()
if sel_tier != "All Tiers":
filt_17k = filt_17k[filt_17k["catalog_intelligence_tier"] == sel_tier]
if search_17k:
filt_17k = filt_17k[filt_17k["name"].str.contains(search_17k, case=False, na=False)]
head1, head2 = st.columns([3, 1])
with head1:
st.markdown("<h2 style='margin-bottom: 2px;'>🌐 Global Master Artist Catalog (17k)</h2>", unsafe_allow_html=True)
st.markdown("<p style='color: #9ca3af; font-size: 0.92rem;'>Empirical registry validation via CSPC sales, RIAA certifications, and verified Last.fm global scrobbles.</p>", unsafe_allow_html=True)
with head2:
st.markdown(f"<div style='text-align: right; color: #6b7280; font-size: 0.8rem; padding-top: 10px;'>Filtered: <b>{len(filt_17k):,} / {len(df_17k):,}</b> acts</div>", unsafe_allow_html=True)
# 17k Macro KPIs
mk1, mk2, mk3, mk4, mk5 = st.columns(5)
with mk1:
st.markdown(f'<div class="kpi-box"><div class="kpi-title">Universe Size</div><div class="kpi-value">{len(df_17k):,}</div><div class="kpi-subtitle">Total Cataloged</div></div>', unsafe_allow_html=True)
with mk2:
ver_cnt = df_17k["catalog_rank"].notna().sum()
st.markdown(f'<div class="kpi-box"><div class="kpi-title" style="color: #10b981;">Verified Entities</div><div class="kpi-value" style="color: #10b981;">{ver_cnt:,}</div><div class="kpi-subtitle">Registry Authenticated</div></div>', unsafe_allow_html=True)
with mk3:
t1_cnt = (df_17k["catalog_intelligence_tier"] == "TIER_1_GLOBAL_SUPERSTAR_CSPC").sum()
st.markdown(f'<div class="kpi-box"><div class="kpi-title" style="color: #f59e0b;">Tier 1 Superstars</div><div class="kpi-value" style="color: #f59e0b;">{t1_cnt:,}</div><div class="kpi-subtitle">Audited CSPC EAS</div></div>', unsafe_allow_html=True)
with mk4:
lfm_cnt = (df_17k["catalog_intelligence_tier"] == "TIER_3_LASTFM_VERIFIED_ENTITY").sum()
st.markdown(f'<div class="kpi-box"><div class="kpi-title" style="color: #38bdf8;">Last.fm Verified</div><div class="kpi-value" style="color: #38bdf8;">{lfm_cnt:,}</div><div class="kpi-subtitle">Active Platform Entities</div></div>', unsafe_allow_html=True)
with mk5:
unver_cnt = len(df_17k) - ver_cnt
st.markdown(f'<div class="kpi-box"><div class="kpi-title" style="color: #ef4444;">Unaudited</div><div class="kpi-value" style="color: #ef4444;">{unver_cnt:,}</div><div class="kpi-subtitle">Zero-Registry Matches</div></div>', unsafe_allow_html=True)
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
# 17k Table
render_cols = [
"catalog_rank", "tier_rank", "name", "catalog_intelligence_tier",
"audited_sales_units", "lastfm_listeners", "lastfm_playcount", "lastfm_url"
]
disp_cols = [c for c in render_cols if c in filt_17k.columns]
st.dataframe(
filt_17k[disp_cols].reset_index(drop=True),
use_container_width=True,
height=560,
column_config={
"catalog_rank": st.column_config.NumberColumn("Global Rank", format="#%d", width="small"),
"tier_rank": st.column_config.NumberColumn("Tier Rank", format="#%d", width="small"),
"name": st.column_config.TextColumn("Artist Name", width="medium"),
"catalog_intelligence_tier": st.column_config.TextColumn("Registry Tier", width="medium"),
"audited_sales_units": st.column_config.NumberColumn("Audited Sales Units", format="%,d", width="medium"),
"lastfm_listeners": st.column_config.NumberColumn("Verified Listeners", format="%,d", width="medium"),
"lastfm_playcount": st.column_config.NumberColumn("Global Scrobbles", format="%,d", width="medium"),
"lastfm_url": st.column_config.LinkColumn("Last.fm Profile", width="small")
}
)
with st.sidebar:
st.markdown("##### 💾 17k Data Export")
csv_17k = filt_17k.to_csv(index=False).encode("utf-8")
st.download_button("📥 Export 17k Table CSV", data=csv_17k, file_name="master_17k_catalog.csv", mime="text/csv", use_container_width=True)
# =====================================================================
# MODULE 2: HIFFI HIP-HOP 500 (ORIGINAL EXECUTIVE DASHBOARD)
# =====================================================================
else:
df = df_500
with st.sidebar:
view_mode = st.radio(
"Leaderboard Perspective:",
[
"🏆 Published Multi-Platform Rank",
"🚀 Breakout Velocity (BVI)",
"💿 Record Sales (CSPC Methodology)",
"🧪 Commercial Simulation Engine (CPI)",
"🔍 Full Cohort Audit Grid",
],
index=0,
)
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
catalog_filter = "All Monitored Artists (500)"
if view_mode in ("💿 Record Sales (CSPC Methodology)", "🧪 Commercial Simulation Engine (CPI)"):
st.markdown("##### 🔍 Sales Catalog Scope")
catalog_filter = st.radio(
"Filter Rows by Sales Telemetry:",
["All Monitored Artists (500)", "Verified Only (321)", "Pure CSPC Only (62)"],
index=0,
)
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
sim_weight = 0.15
sim_mode = "matched_only"
if view_mode == "🧪 Commercial Simulation Engine (CPI)" and engine is not None:
st.markdown("##### 🧪 Simulation Parameters")
sim_mode_choice = st.radio(
"Evaluation Scope:",
["🎯 Matched Cohort Only", "🌐 Global Cohort (N=500, Weight Redistribution)"],
index=1 if catalog_filter == "All Monitored Artists (500)" else 0,
)
sim_mode = "matched_only" if "Matched" in sim_mode_choice else "global_redistribution"
sim_weight = st.select_slider(
"Commercial Signal Weight:",
options=[0.0, 0.05, 0.10, 0.15, 0.20],
value=0.15,
format_func=lambda x: f"{int(x*100)}% Commercial",
)
st.caption(f"Baseline Score Weight: **{int((1.0 - sim_weight)*100)}%**")
st.markdown("<div class='custom-divider'></div>", 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)
# Filter logic
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()
if catalog_filter == "Pure CSPC Only (62)":
filtered_df = filtered_df[filtered_df["sales_data_status"] == "VERIFIED_CSPC"].copy()
elif catalog_filter == "Verified Only (321)":
filtered_df = filtered_df[filtered_df["sales_data_status"].isin(["VERIFIED_CSPC", "VERIFIED_RIAA"])].copy()
sim_metrics = {}
if view_mode == "🧪 Commercial Simulation Engine (CPI)" and engine is not None:
try:
filtered_df = engine.simulate_ranking(filtered_df, commercial_weight=sim_weight, mode=sim_mode)
sim_metrics = engine.compute_simulation_metrics(filtered_df)
except Exception:
pass
with st.sidebar:
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
st.markdown("##### 💾 Unified Audit Exports")
if generate_executive_sales_workbook is not None:
try:
excel_workbook_bytes = generate_executive_sales_workbook(filtered_df, commercial_weight=sim_weight, mode=sim_mode)
st.download_button(
"📊 Multi-Tab Audit Excel (.xlsx)",
data=excel_workbook_bytes,
file_name="hiffi_executive_sales_audit.xlsx",
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
use_container_width=True,
)
except Exception:
pass
csv_payload = filtered_df.to_csv(index=False).encode("utf-8")
st.download_button(
"📥 Filtered Table CSV",
data=csv_payload,
file_name="hiffi_multiplatform_filtered.csv",
mime="text/csv",
use_container_width=True,
)
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
st.caption("Governance: CSPC Methodology • EAS Units • Zero-Imputation Compliant")
head_col1, head_col2 = st.columns([3, 1])
with head_col1:
st.markdown("<h2 style='margin-bottom: 2px;'>HIFFI Hip-Hop 500 Intelligence Hub</h2>", unsafe_allow_html=True)
st.markdown("<p style='color: #9ca3af; font-size: 0.92rem; margin-top: 0;'>Multi-platform composite rankings with zero-imputation policy, dynamic weight redistribution, and verified record sales.</p>", unsafe_allow_html=True)
with head_col2:
st.markdown(
f"<div style='text-align: right; color: #6b7280; font-size: 0.8rem; padding-top: 10px;'>Filtered Cohort: <b>{len(filtered_df)} / {len(df)}</b> artists</div>",
unsafe_allow_html=True,
)
# 500 Macro KPI Cards
k1, k2, k3, k4, k5 = st.columns(5)
with k1:
st.markdown(f'<div class="kpi-box"><div class="kpi-title">Tracked Artists</div><div class="kpi-value">{len(df)}</div><div class="kpi-subtitle">Monitored Cohort</div></div>', unsafe_allow_html=True)
with k2:
t3_count = len(df[df["platform_evidence_tier"] == 3])
st.markdown(f'<div class="kpi-box"><div class="kpi-title" style="color: #10b981;">Tier 3 (Complete)</div><div class="kpi-value" style="color: #10b981;">{t3_count}</div><div class="kpi-subtitle">YouTube + Spotify + Instagram</div></div>', unsafe_allow_html=True)
with k3:
sp_count = df["spotify_monthly_listeners"].notna().sum()
st.markdown(f'<div class="kpi-box"><div class="kpi-title" style="color: #38bdf8;">Spotify Telemetry</div><div class="kpi-value" style="color: #38bdf8;">{sp_count}</div><div class="kpi-subtitle">Verified monthly listeners</div></div>', unsafe_allow_html=True)
with k4:
ig_count = df["instagram_followers"].notna().sum()
st.markdown(f'<div class="kpi-box"><div class="kpi-title" style="color: #f59e0b;">Instagram Audience</div><div class="kpi-value" style="color: #f59e0b;">{ig_count}</div><div class="kpi-subtitle">Verified public followings</div></div>', unsafe_allow_html=True)
with k5:
cataloged_count = df["total_eas_cspc"].fillna(0).gt(0).sum()
st.markdown(f'<div class="kpi-box"><div class="kpi-title" style="color: #ec4899;">Catalog Coverage</div><div class="kpi-value" style="color: #ec4899;">{cataloged_count}</div><div class="kpi-subtitle">100% Cohort Cataloged</div></div>', unsafe_allow_html=True)
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
if view_mode in ("💿 Record Sales (CSPC Methodology)", "🧪 Commercial Simulation Engine (CPI)"):
verified_cspc_cnt = int((df["sales_data_status"] == "VERIFIED_CSPC").sum())
verified_riaa_cnt = int((df["sales_data_status"] == "VERIFIED_RIAA").sum())
estimated_sea_cnt = int((df["sales_data_status"] == "ESTIMATED_SEA").sum())
total_active_coverage = verified_cspc_cnt + verified_riaa_cnt + estimated_sea_cnt
coverage_pct = (total_active_coverage / len(df)) * 100.0
st.markdown(
f"""
<div class="coverage-card">
<div>
<span style="font-weight: 800; color: #f9fafb; font-size: 0.92rem;">📡 Commercial Telemetry Coverage Progress:</span>
<span style="color: #10b981; font-weight: 700; margin-left: 8px;">{verified_cspc_cnt} CSPC Verified</span>
<span style="color: #64748b; margin: 0 6px;">•</span>
<span style="color: #38bdf8; font-weight: 700;">{verified_riaa_cnt} RIAA Certified</span>
<span style="color: #64748b; margin: 0 6px;">•</span>
<span style="color: #a855f7; font-weight: 600;">{estimated_sea_cnt} Streaming SEA</span>
</div>
<div style="font-size: 0.85rem; color: #94a3b8;">
Active Commercial Coverage: <strong style="color: #10b981;">{coverage_pct:.1f}%</strong> ({total_active_coverage}/{len(df)})
</div>
</div>
""",
unsafe_allow_html=True,
)
if view_mode == "💿 Record Sales (CSPC Methodology)":
st.markdown("### 💿 Global Record Sales & Lifetime Commercial Ranking")
st.caption("Standardized on ChartMasters CSPC, verified RIAA certifications, and video/audio streaming equivalent units.")
sc1, sc2, sc3, sc4 = st.columns(4)
total_sales_volume = filtered_df["total_eas_cspc"].fillna(0).sum()
cspc_count = (filtered_df["sales_data_status"] == "VERIFIED_CSPC").sum()
riaa_count = (filtered_df["sales_data_status"] == "VERIFIED_RIAA").sum()
sea_count = (filtered_df["sales_data_status"] == "ESTIMATED_SEA").sum()
with sc1:
st.markdown(f'<div class="kpi-box"><div class="kpi-title">Tracked Catalog Volume</div><div class="kpi-value">{total_sales_volume/1e6:.1f}M</div><div class="kpi-subtitle">Total Equivalent Album Sales (EAS)</div></div>', unsafe_allow_html=True)
with sc2:
st.markdown(f'<div class="kpi-box"><div class="kpi-title" style="color: #10b981;">CSPC Verified</div><div class="kpi-value" style="color: #10b981;">{cspc_count}</div><div class="kpi-subtitle">ChartMasters Full Dossiers</div></div>', unsafe_allow_html=True)
with sc3:
st.markdown(f'<div class="kpi-box"><div class="kpi-title" style="color: #38bdf8;">RIAA Certified</div><div class="kpi-value" style="color: #38bdf8;">{riaa_count}</div><div class="kpi-subtitle">Domestic Certifications</div></div>', unsafe_allow_html=True)
with sc4:
st.markdown(f'<div class="kpi-box"><div class="kpi-title" style="color: #a855f7;">Streaming SEA</div><div class="kpi-value" style="color: #a855f7;">{sea_count}</div><div class="kpi-subtitle">Luminate/Billboard Conversion</div></div>', unsafe_allow_html=True)
st.markdown("#### 🏆 All-Time Global Sales Leaderboard")
sales_table_df = filtered_df.sort_values(by="total_eas_cspc", ascending=False).copy()
sales_table_df["provenance_badge"] = sales_table_df["sales_data_status"].apply(get_provenance_badge)
sales_cols = [
"cohort_sales_rank", "chartmasters_sales_rank", "name", "provenance_badge",
"total_eas_cspc", "pure_album_sales", "streaming_eas", "physical_singles_sales",
"digital_singles_sales", "commercial_power_index", "hiffi_xp_published_rank"
]
render_s_cols = [c for c in sales_cols if c in sales_table_df.columns]
st.dataframe(
sales_table_df[render_s_cols].reset_index(drop=True),
use_container_width=True,
height=380,
column_config={
"cohort_sales_rank": st.column_config.NumberColumn("Cohort Sales Rank", format="#%d", width="small"),
"chartmasters_sales_rank": st.column_config.NumberColumn("All-Time Global Rank", format="#%d", width="small"),
"name": st.column_config.TextColumn("Artist", width="medium"),
"provenance_badge": st.column_config.TextColumn("Audit Provenance", width="medium"),
"total_eas_cspc": st.column_config.NumberColumn("Total EAS Units", format="%,d", width="medium"),
"pure_album_sales": st.column_config.NumberColumn("Pure Studio 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 Singles", format="%,d", width="small"),
"digital_singles_sales": st.column_config.NumberColumn("Digital Downloads", format="%,d", width="small"),
"commercial_power_index": st.column_config.ProgressColumn("CPI Score", min_value=0, max_value=100, format="%.1f", width="small"),
"hiffi_xp_published_rank": st.column_config.NumberColumn("HIFFI Base Rank", format="#%d", width="small"),
},
)
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
c_s1, c_s2 = st.columns(2)
with c_s1:
top_sellers = sales_table_df[sales_table_df["total_eas_cspc"] > 0].head(12)
fig_format = go.Figure()
fig_format.add_trace(go.Bar(name="Traditional Albums", x=top_sellers["name"], y=top_sellers["pure_album_sales"], marker_color="#8b5cf6"))
fig_format.add_trace(go.Bar(name="Digital Singles", x=top_sellers["name"], y=top_sellers["digital_singles_sales"], marker_color="#38bdf8"))
fig_format.add_trace(go.Bar(name="Streaming EAS", x=top_sellers["name"], y=top_sellers["streaming_eas"], marker_color="#10b981"))
fig_format.update_layout(
barmode="stack", title="Format Contribution: Pure Albums vs Downloads vs Streaming EAS",
template="plotly_dark", paper_bgcolor="#111827", plot_bgcolor="#111827",
font=dict(color="#9ca3af"), height=360, margin=dict(l=20, r=20, t=50, b=20),
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1.0),
)
st.plotly_chart(fig_format, use_container_width=True)
with c_s2:
scatter_data = sales_table_df.dropna(subset=["total_eas_cspc", "hiffi_xp_score"]).copy()
fig_quad = px.scatter(
scatter_data, x="hiffi_xp_score", y="total_eas_cspc", size="total_eas_cspc",
color="provenance_badge", hover_name="name", log_y=True,
title="Legacy vs. Velocity Quadrant (All-Time Sales vs HIFFI-XP)",
labels={"hiffi_xp_score": "Current Velocity (HIFFI-XP)", "total_eas_cspc": "Total Lifetime EAS Units (Log Scale)"},
template="plotly_dark",
)
fig_quad.update_layout(paper_bgcolor="#111827", plot_bgcolor="#111827", font=dict(color="#9ca3af"), height=360, margin=dict(l=20, r=20, t=50, b=20))
st.plotly_chart(fig_quad, use_container_width=True)
else:
top3 = filtered_df.sort_values(by="hiffi_xp_published_rank", ascending=True).head(3)
if len(top3) >= 3 and view_mode != "🧪 Commercial Simulation Engine (CPI)":
st.markdown("#### 👑 Market Leaders (Published Baseline 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))
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"""
<div class="podium-tile {css_class}">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px;">
<span style="font-weight: 800; color: {accent_color}; font-size: 0.85rem;">{rank_label}</span>
<span class="badge badge-tier{tier_val}">Tier {tier_val} Evidence</span>
</div>
<div style="font-size: 1.35rem; font-weight: 800; color: #ffffff; margin-bottom: 2px;">{row_data['name']}</div>
<div style="font-size: 0.8rem; color: #6b7280; margin-bottom: 12px;">{row_data.get('channel_title', '')}</div>
<div style="display: flex; justify-content: space-between; background: #0b0f17; padding: 10px 14px; border-radius: 8px;">
<div><div style="font-size: 0.68rem; color: #9ca3af;">HIFFI-XP</div><div style="font-size: 1.25rem; font-weight: 800; color: {accent_color};">{row_data['hiffi_xp_score']:.2f}</div></div>
<div><div style="font-size: 0.68rem; color: #9ca3af;">Spotify Monthly</div><div style="font-size: 1.05rem; font-weight: 700; color: #38bdf8;">{sp_str}</div></div>
<div><div style="font-size: 0.68rem; color: #9ca3af;">IG Followers</div><div style="font-size: 1.05rem; font-weight: 700; color: #e5e7eb;">{ig_str}</div></div>
</div>
</div>
""",
unsafe_allow_html=True,
)
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
if view_mode == "🧪 Commercial Simulation Engine (CPI)":
st.markdown("#### 🧪 Simulation Impact & Decision Summary")
sm1, sm2, sm3, sm4 = st.columns(4)
g_delta = f"+{sim_metrics.get('top_gainer_delta', 0)}" if sim_metrics.get('top_gainer_delta', 0) > 0 else f"{sim_metrics.get('top_gainer_delta', 0)}"
l_delta = f"{sim_metrics.get('top_loser_delta', 0)}"
with sm1:
st.markdown(f'<div class="sim-kpi-card"><div class="sim-kpi-title">Top Gainer</div><div class="sim-kpi-val" style="color: #10b981;">{sim_metrics.get("top_gainer_name", "None")} <span style="font-size: 0.85rem;">(▲ {g_delta})</span></div></div>', unsafe_allow_html=True)
with sm2:
st.markdown(f'<div class="sim-kpi-card"><div class="sim-kpi-title">Top Loser</div><div class="sim-kpi-val" style="color: #ef4444;">{sim_metrics.get("top_loser_name", "None")} <span style="font-size: 0.85rem;">(▼ {l_delta})</span></div></div>', unsafe_allow_html=True)
with sm3:
st.markdown(f'<div class="sim-kpi-card"><div class="sim-kpi-title">Mean Absolute Shift</div><div class="sim-kpi-val" style="color: #38bdf8;">± {sim_metrics.get("mean_abs_delta", 0.0)} <span style="font-size: 0.85rem; color: #94a3b8;">positions</span></div></div>', unsafe_allow_html=True)
with sm4:
st.markdown(f'<div class="sim-kpi-card"><div class="sim-kpi-title">Simulation Scope</div><div class="sim-kpi-val" style="color: #f59e0b;">{sim_metrics.get("matched_coverage", 0)} / {len(filtered_df)} <span style="font-size: 0.85rem; color: #94a3b8;">({sim_mode})</span></div></div>', unsafe_allow_html=True)
st.caption(f"💡 **Executive Takeaway:** At **{int(sim_weight*100)}% commercial weight**, the average cataloged artist moves **±{sim_metrics.get('mean_abs_delta', 0.0)} positions**.")
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
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 == "🧪 Commercial Simulation Engine (CPI)":
table_df = filtered_df.sort_values(by="simulated_rank", ascending=True).copy()
def format_rank_delta(val):
if pd.isna(val):
return "N/A"
ival = int(val)
if ival > 0:
return f"▲ +{ival} (Up)"
elif ival < 0:
return f"▼ {ival} (Down)"
else:
return "— 0 (Equal)"
table_df["rank_shift_indicator"] = table_df["simulation_rank_delta"].apply(format_rank_delta)
comp_rank = "baseline_matched_rank" if sim_mode == "matched_only" else "hiffi_xp_published_rank"
cols = [
"simulated_rank", comp_rank, "rank_shift_indicator", "name",
"simulated_hiffi_score", "hiffi_xp_score", "commercial_power_index",
"total_eas_cspc", "sales_data_status",
]
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"]
display_table = table_df.copy()
if "sales_data_status" in display_table.columns:
display_table["sales_data_status"] = display_table["sales_data_status"].apply(get_provenance_badge)
render_cols = [c for c in cols if c in display_table.columns]
st.dataframe(
display_table[render_cols].reset_index(drop=True),
use_container_width=True,
height=340,
column_config={
"hiffi_xp_published_rank": st.column_config.NumberColumn("Published Rank", format="%d", width="small"),
"baseline_matched_rank": st.column_config.NumberColumn("Baseline Match Rank", format="%d", width="small"),
"simulated_rank": st.column_config.NumberColumn("Simulated Rank", format="%d", width="small"),
"rank_shift_indicator": st.column_config.TextColumn("Simulated Δ (Movement)", width="medium"),
"simulated_hiffi_score": st.column_config.ProgressColumn("Simulated Score", format="%.2f", min_value=0, max_value=100, width="medium"),
"hiffi_xp_score": st.column_config.ProgressColumn("HIFFI-XP Score", format="%.2f", min_value=0, max_value=100, width="medium"),
"commercial_power_index": st.column_config.ProgressColumn("Commercial Power Index", format="%.1f", min_value=0, max_value=100, width="medium"),
"total_eas_cspc": st.column_config.NumberColumn("Total Equivalent Album Sales", format="%,d", width="medium"),
"pure_album_sales": st.column_config.NumberColumn("Traditional Album Sales", format="%,d", width="medium"),
"streaming_eas": st.column_config.NumberColumn("Streaming-Equivalent Album Sales", format="%,d", width="medium"),
"sales_data_status": st.column_config.TextColumn("Sales Audit Status", width="medium"),
},
)
st.markdown("<div class='custom-divider'></div>", unsafe_allow_html=True)
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"), height=320, margin=dict(l=20, r=20, t=40, b=20))
st.plotly_chart(fig_scatter, use_container_width=True)
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"), height=320, margin=dict(l=20, r=20, t=40, b=20))
st.plotly_chart(fig_pie, use_container_width=True)
# Dossier for 500
st.markdown("<div class='custom-divider'></div>", 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 "Awaiting Ingestion")
st.markdown(
f"""
<div style="background: #111827; padding: 14px 18px; border-radius: 8px; border: 1px solid #1f2937; margin-top: 10px; font-size: 0.85rem;">
<div style="display: flex; gap: 20px; flex-wrap: wrap;">
<div><b>Artist:</b> {row['name']}</div>
<div><b>Evidence Tier:</b> Tier {int(row.get('platform_evidence_tier', 1))}</div>
<div><b>Global Sales Rank:</b> {f"#{int(row.get('chartmasters_sales_rank'))}" if pd.notna(row.get('chartmasters_sales_rank')) else "Unranked"}</div>
<div><b>Cohort Sales Rank:</b> {f"#{int(row.get('cohort_sales_rank'))}" if pd.notna(row.get('cohort_sales_rank')) else "Uncataloged"}</div>
<div><b>Commercial Power Index:</b> {f"{row.get('commercial_power_index'):.1f}" if pd.notna(row.get('commercial_power_index')) else "Awaiting Audit"}</div>
<div><b>Traditional Albums:</b> {f"{int(row.get('pure_album_sales')):,}" if pd.notna(row.get('pure_album_sales')) else "N/A"}</div>
<div><b>Streaming-Equivalent EAS:</b> {f"{int(row.get('streaming_eas')):,}" if pd.notna(row.get('streaming_eas')) else "N/A"}</div>
<div><b>Sales Status:</b> {get_provenance_badge(row.get('sales_data_status', ''))}</div>
</div>
</div>
""",
unsafe_allow_html=True,
)