eGFR_SLE_ / app.py
DocSrvNyk's picture
Update app.py
6ba05f3 verified
import gradio as gr
import numpy as np
import plotly.graph_objects as go
# Final model coefficients from Elastic Net
INTERCEPT = 2.384
COEFS = {
"Age": -0.112,
"C3": -0.327,
"C4": -0.053,
"C3/C4": -0.166,
"Ln_C3C4": 0.135,
"Ln_C4C3": -0.135
}
THRESHOLD = 0.461
# ------------------------
# Prediction Function
# ------------------------
def predict(age, c3, c4):
if c4 == 0 or c3 == 0:
return "Invalid input", None, None, "C3 and C4 must be > 0", ""
c3_c4 = c3 / c4
ln_c3c4 = np.log(c3_c4)
ln_c4c3 = np.log(c4 / c3)
logit = INTERCEPT + (
COEFS["Age"] * age +
COEFS["C3"] * c3 +
COEFS["C4"] * c4 +
COEFS["C3/C4"] * c3_c4 +
COEFS["Ln_C3C4"] * ln_c3c4 +
COEFS["Ln_C4C3"] * ln_c4c3
)
prob = 1 / (1 + np.exp(-logit))
label = "Likely To Develop Renal Complications" if prob > THRESHOLD else "Not Likely To Develop Renal Complications"
confidence = f"Model confidence: {round(prob * 100 if prob > THRESHOLD else (1 - prob) * 100)}%"
interpretation = (
"This result indicates a higher-than-threshold probability of developing renal complications. "
"Further clinical evaluation and monitoring is advised."
if prob > THRESHOLD else
"The probability of abnormal renal function appears low. Routine follow-up is sufficient unless other risk factors exist."
)
return label, create_logit_meter(prob), create_prob_gauge(prob), confidence, interpretation
# ------------------------
# Linear Logit Meter
# ------------------------
def create_logit_meter(prob):
fig = go.Figure(go.Indicator(
mode="gauge+number+delta",
value=prob,
number={'valueformat': ".3f", 'font': {'size': 36, 'color': "black"}},
delta={'reference': THRESHOLD, 'increasing': {'color': "red"}, 'decreasing': {'color': "green"}},
gauge={
'shape': "bullet",
'axis': {
'range': [0, 1],
'tickwidth': 2,
'tickcolor': "#666",
'tickfont': {'size': 16}
},
'bar': {'color': "blue", 'thickness': 0.4},
'steps': [
{'range': [0, THRESHOLD], 'color': "#ccffcc"},
{'range': [THRESHOLD, 1], 'color': "#ad3d46"}
],
'threshold': {
'line': {'color': "black", 'width': 4},
'thickness': 0.8,
'value': THRESHOLD
},
},
title={
"text": f"Logit Risk Probability",
"font": {'size': 18}
},
domain={'x': [0, 1], 'y': [0, 1]}
))
fig.update_layout(
height=240,
paper_bgcolor="white",
font=dict(family="Arial", size=16, color="black"),
margin=dict(t=40, b=30, l=10, r=10)
)
return fig
# ------------------------
# Dynamic Probability Gauge
# ------------------------
def create_prob_gauge(prob):
if prob > THRESHOLD:
gauge_value = prob
title = "Probability of Abnormal Renal Function"
steps = [
{'range': [0, 0.33], 'color': "lightgreen"},
{'range': [0.33, 0.66], 'color': "orange"},
{'range': [0.66, 1], 'color': "red"}
]
else:
gauge_value = 1 - prob
title = "Probability of Normal Renal Function"
steps = [
{'range': [0, 0.33], 'color': "red"},
{'range': [0.33, 0.66], 'color': "orange"},
{'range': [0.66, 1], 'color': "lightgreen"}
]
fig = go.Figure(go.Indicator(
mode="gauge+number",
value=gauge_value,
number={'valueformat': ".0%"},
gauge={
'axis': {'range': [0, 1]},
'bar': {'color': "black"},
'steps': steps,
},
title={"text": title}
))
fig.update_layout(height=500, margin=dict(t=10, b=10, l=10, r=10))
return fig
# ------------------------
# Gradio Interface
# ------------------------
demo = gr.Interface(
fn=predict,
inputs=[
gr.Slider(5, 18, step=0.5, label="Age (Years)"),
gr.Number(label="C3 Level (mg/dL)"),
gr.Number(label="C4 Level (mg/dL)")
],
outputs=[
gr.Text(label="Screening Verdict"),
gr.Plot(label="Logit Risk Meter"),
gr.Plot(label="Risk Probability Gauge"),
gr.Text(label="Model Confidence"),
gr.Textbox(label="Interpretation", lines=3)
],
title="🧪 Renal Complication Prediction Tool In Cases With Paediatric SLE",
description="Enter Age, C3, and C4 levels to Predict Probability of Future Renal Complication based on a validated dataset of Paeditric SLE dataset by robust Elastic Net Regression."
)
demo.launch()