zaheerjk's picture
Upload 14 files
ed42c5c verified
Raw
History Blame Contribute Delete
9.2 kB
import streamlit as st
import pandas as pd
import numpy as np
import joblib
# Configured for wide mode to utilize all available screen space beautifully
st.set_page_config(
page_title='Cancer Risk Predictor',
layout='wide',
initial_sidebar_state='collapsed'
)
@st.cache_resource
def load_artifacts():
model = joblib.load('Models/model_xgb_new.pkl')
le = joblib.load('Models/Label_encoder.pkl')
feature_name = joblib.load('Models/Feature_names.pkl')
return model, le, feature_name
model, le, FEATURE_NAMES = load_artifacts()
# --- HEADER SECTION ---
st.title("🧬 Cancer Risk Level Predictor")
st.markdown("Assess patient risk levels using advanced machine learning diagnostics. Choose a processing mode below.")
# Native Tabs look much cleaner and more professional than radio buttons for application routing
tab_batch, tab_manual = st.tabs(["📁 Batch Processing (CSV Upload)", "👤 Individual Patient Intake"])
def preprocess_input(df):
missing = [c for c in FEATURE_NAMES if c not in df.columns]
if missing:
st.warning(f"⚠️ Missing Columns in input - Filling {len(missing)} fields with zero : {missing}")
for c in missing:
df[c] = 0
df = df[FEATURE_NAMES].copy()
df = df.apply(pd.to_numeric, errors='coerce').fillna(0)
return df
# ==========================================
# 📁 BATCH PROCESSING MODE
# ==========================================
with tab_batch:
st.subheader("Batch Dataset Analysis")
st.markdown("Upload a patient population roster to parse risk profiles simultaneously.")
uploaded_file = st.file_uploader("Drop your dataset here", type=['csv'], label_visibility="collapsed")
if uploaded_file is not None:
input_df = pd.read_csv(uploaded_file)
with st.spinner("Processing framework algorithms..."):
x = preprocess_input(input_df)
pred_enc = model.predict(x)
probs = model.predict_proba(x)
preds = le.inverse_transform(pred_enc)
result = x.copy()
result['Predicted_Risk_Level'] = preds
for i, cls in enumerate(le.classes_):
result[f'prob_{cls}'] = probs[:, i]
st.success("✅ Analytics Engine Execution Complete")
# Native interactive data frames allow users to filter, sort, and search right out of the box
st.dataframe(result, use_container_width=True)
st.download_button(
label="📥 Download Structured Predictions CSV",
data=result.to_csv(index=False),
file_name='predictions.csv',
mime='text/csv',
type='secondary'
)
# ==========================================
# 👤 INDIVIDUAL PATIENT INTAKE MODE
# ==========================================
with tab_manual:
st.subheader("Manual Clinical Intake Form")
# Using a native bordered container to logically isolate the entry parameters
with st.container(border=True):
st.markdown("#### 🩺 Demographics & Administrative Meta")
c_meta1, c_meta2, c_meta3, c_meta4 = st.columns(4)
input_data = {}
with c_meta1:
input_data['Patient_ID'] = st.text_input("Patient Identification ID", value="LU0005")
with c_meta2:
input_data['Cancer_Type'] = st.selectbox("Suspected Target System", ['Breast', 'Prostate', 'Skin', 'Colon', 'Lung'])
with c_meta3:
input_data['Age'] = st.number_input("Biological Age (Years)", min_value=0, max_value=120, value=50)
with c_meta4:
input_data['Gender'] = st.selectbox("Biological Sex Assigned", [0, 1], format_func=lambda x: "Female" if x == 0 else "Male")
with st.container(border=True):
st.markdown("#### ⚖️ Physiological Vitals & Laboratory Scoring")
c_phys1, c_phys2, c_phys3 = st.columns(3)
with c_phys1:
input_data['BMI'] = st.number_input("Body Mass Index (BMI)", min_value=10.0, max_value=60.0, value=25.0, step=0.1)
with c_phys2:
input_data['Overall_Risk_Score'] = st.number_input("Pre-evaluation Baseline Risk Score", min_value=0.0, max_value=1.0, value=0.4, step=0.01)
with c_phys3:
input_data['Calcium_Intake'] = st.slider("Dietary Calcium Scaling (0-10)", 0, 10, 5)
with st.container(border=True):
st.markdown("#### 🧬 Genetic & Pathogenic Pre-dispositions")
c_gen1, c_gen2, c_gen3 = st.columns(3)
with c_gen1:
input_data['Family_History'] = st.selectbox("Family Oncological History", [0, 1], format_func=lambda x: "No History" if x == 0 else "Positive History")
with c_gen2:
input_data['BRCA_Mutation'] = st.selectbox("BRCA Variant Mutation Status", [0, 1], format_func=lambda x: "Negative / Normal" if x == 0 else "Positive Marker Present")
with c_gen3:
input_data['H_Pylori_Infection'] = st.selectbox("Active H. Pylori Infection Status", [0, 1], format_func=lambda x: "Negative" if x == 0 else "Positive Exposure")
with st.container(border=True):
st.markdown("#### 🚬 Behavioral Habits & Environmental Exposures")
c_beh1, c_beh2 = st.columns(2)
with c_beh1:
input_data['Smoking'] = st.slider("Tobacco / Smoking Exposure Severity (0-10)", 0, 10, 0)
input_data['Alcohol_Use'] = st.slider("Alcohol Consumption Volume Scale (0-10)", 0, 10, 0)
input_data['Obesity'] = st.slider("Clinical Obesity Stratification Index (0-10)", 0, 10, 0)
input_data['Physical_Activity'] = st.slider("Physical Activity Engagement Metric (0-10)", 0, 10, 5)
with c_beh2:
input_data['Diet_Red_Meat'] = st.slider("Red Meat Consumption Frequency (0-10)", 0, 10, 0)
input_data['Diet_Salted_Processed'] = st.slider("Processed / Sodium Food Prevalence (0-10)", 0, 10, 0)
input_data['Fruit_Veg_Intake'] = st.slider("Nutritional Fruit & Vegetable Density (0-10)", 0, 10, 5)
input_data['Physical_Activity_Level'] = st.slider("Cardio / Physical Exertion Intensity Level (0-10)", 0, 10, 5)
with st.container(border=True):
st.markdown("#### 🏭 Ecological & Occupational Conditions")
c_eco1, c_eco2 = st.columns(2)
with c_eco1:
input_data['Air_Pollution'] = st.slider("Particulate Air Pollution Hazard Scale (0-10)", 0, 10, 2)
with c_eco2:
input_data['Occupational_Hazards'] = st.slider("Workplace Carcinogen Exposure Scale (0-10)", 0, 10, 2)
# Centered Primary Call to Action Button
_, btn_col, _ = st.columns([2, 1, 2])
with btn_col:
predict_triggered = st.button("🔬 Compute Comprehensive Risk Profile", type="primary", use_container_width=True)
if predict_triggered:
x_single = pd.DataFrame([input_data])
x_proc = preprocess_input(x_single)
pred_enc = model.predict(x_proc)[0]
probs = model.predict_proba(x_proc)[0]
pred = le.inverse_transform([pred_enc])[0]
st.markdown("---")
st.subheader("📋 Core Diagnostic Output Results")
# UI Upgrade: Using native high-impact metric cards instead of just plain text
c_res1, c_res2 = st.columns([2, 3])
with c_res1:
st.metric(label="Calculated Stratified Risk Target Level", value=f"{pred}")
# Extract High risk threshold probability safely
high_prob_val = probs[list(le.classes_).index('High')] if 'High' in le.classes_ else 0.0
st.metric(label="Absolute High-Risk Probability Node Index", value=f"{high_prob_val:.2%}")
if high_prob_val >= 0.5:
st.warning("⚠️ **ALERT:** Patient assessment metrics exceed the preset danger threshold parameters. Immediate triage or secondary clinical review is strongly advised.")
else:
st.success("✅ **STABLE:** Calculated biomarkers indicate the individual falls within normalized operating action baselines.")
with c_res2:
st.markdown("**Categorical Confidence Vector Matrix**")
prob_df = pd.DataFrame({
'Risk Classification Stratum': list(le.classes_),
'Confidence Interval Probability': probs
}).sort_values('Confidence Interval Probability', ascending=False).reset_index(drop=True)
# Map values to neat percentage layout matrices
prob_df['Confidence Interval Probability'] = prob_df['Confidence Interval Probability'].map(lambda x: f"{x:.2%}")
st.table(prob_df)
st.markdown("---")
st.caption("⚙️ Diagnostic Engine: Class-Weighted Extreme Gradient Boosting (XGBoost Architecture optimized via Optuna framework). Check your input array configurations against standard evaluation models before deploying to clinical trials.")