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()