Sumitkumar098 commited on
Commit
3f39d64
·
verified ·
1 Parent(s): dc21e75

Initial application upload

Browse files
app.py ADDED
@@ -0,0 +1,449 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import joblib
4
+ import json
5
+ import warnings
6
+ import plotly.express as px
7
+ from streamlit_card import card
8
+ # Add these imports for PDF generation
9
+ from fpdf import FPDF
10
+ from datetime import datetime
11
+ warnings.filterwarnings("ignore", message="X does not have valid feature names")
12
+
13
+ # Page configuration
14
+ st.set_page_config(
15
+ page_title="Medical Outcome Predictor",
16
+ page_icon="🏥",
17
+ layout="wide",
18
+ initial_sidebar_state="expanded"
19
+ )
20
+
21
+ # Add custom CSS
22
+ st.markdown("""
23
+ <style>
24
+ .main-header {
25
+ font-size: 2.5rem;
26
+ color: #1E88E5;
27
+ font-weight: 700;
28
+ }
29
+ .sub-header {
30
+ font-size: 1.5rem;
31
+ color: #424242;
32
+ font-weight: 600;
33
+ border-bottom: 1px solid #f0f0f0;
34
+ padding-bottom: 1rem;
35
+ }
36
+ .prediction-header {
37
+ font-size: 1.8rem;
38
+ color: #1E88E5;
39
+ font-weight: 600;
40
+ margin-top: 2rem;
41
+ }
42
+ .card {
43
+ border-radius: 10px;
44
+ border: 1px solid #e0e0e0;
45
+ padding: 20px;
46
+ margin-bottom: 20px;
47
+ background-color: white;
48
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
49
+ }
50
+ .section-divider {
51
+ height: 2px;
52
+ background-color: #f0f0f0;
53
+ margin: 15px 0;
54
+ }
55
+ </style>
56
+ """, unsafe_allow_html=True)
57
+
58
+ # Utility Functions
59
+ def load_model(model_path):
60
+ return joblib.load(model_path)
61
+
62
+ def encode_input_features(input_features, feature_list):
63
+ return pd.DataFrame([feature_list], columns=input_features)
64
+
65
+ def decode_predictions(predictions, encoders):
66
+ decoded_predictions = {}
67
+ for col in predictions.columns:
68
+ encoder = encoders.get(col)
69
+ if encoder:
70
+ decoded_value = encoder.inverse_transform([predictions[col].iloc[0]])[0]
71
+ decoded_predictions[col] = decoded_value
72
+ else:
73
+ decoded_predictions[col] = "Error: No encoder found"
74
+ return decoded_predictions
75
+
76
+ def get_mapped_outputs(predicted_disease, mappings):
77
+ return mappings.get(predicted_disease, {})
78
+
79
+ def generate_pdf_report(patient_data, prediction_results):
80
+ """Generate a compact professional medical report PDF with patient data and prediction results"""
81
+ pdf = FPDF(orientation='P', unit='mm', format='A4')
82
+ pdf.set_margins(10, 10, 10) # Smaller margins (left, top, right)
83
+ pdf.add_page()
84
+
85
+ # Add headers and styling - more compact
86
+ pdf.set_font("Arial", 'B', 14)
87
+ pdf.cell(190, 6, "Medical Report", ln=True, align='C')
88
+
89
+ # Add patient name in the header if available
90
+ patient_name = patient_data.get('Patient_Name', '')
91
+ if patient_name:
92
+ pdf.set_font("Arial", 'B', 10)
93
+ pdf.cell(190, 4, f"Patient: {patient_name}", ln=True, align='C')
94
+
95
+ pdf.set_font("Arial", 'I', 8)
96
+ pdf.cell(190, 4, f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}", ln=True, align='C')
97
+ pdf.line(10, 24, 200, 24)
98
+ pdf.ln(2)
99
+
100
+ # Two-column layout for patient info and vital signs
101
+ pdf.set_font("Arial", 'B', 10)
102
+ pdf.cell(190, 6, "Patient Information & Vital Signs", ln=True, border=1)
103
+
104
+ # First row
105
+ pdf.set_font("Arial", '', 8)
106
+ pdf.cell(47.5, 5, f"Age: {patient_data['Age']}", 1)
107
+ pdf.cell(47.5, 5, f"Gender: {patient_data['Gender']}", 1)
108
+ pdf.cell(47.5, 5, f"Blood Group: {patient_data['Blood_Group']}", 1)
109
+ pdf.cell(47.5, 5, f"Weight: {patient_data['Weight_kg']} kg", 1, ln=True)
110
+
111
+ # Second row
112
+ pdf.cell(47.5, 5, f"Temp: {patient_data['Temperature_C']}°C", 1)
113
+ pdf.cell(47.5, 5, f"Heart Rate: {patient_data['Heart_Rate']} BPM", 1)
114
+ pdf.cell(47.5, 5, f"BP: {patient_data['BP_Systolic']}/- mmHg", 1)
115
+ pdf.cell(47.5, 5, f"Glucose: {patient_data['Glucose_Level']} mg/dL", 1, ln=True)
116
+
117
+ # Symptoms in a single row
118
+ conditions = []
119
+ if patient_data['Has_Fever']: conditions.append("Fever")
120
+ if patient_data['Has_Cough']: conditions.append("Cough")
121
+ if patient_data['Has_Fatigue']: conditions.append("Fatigue")
122
+ if patient_data['Has_Pain']: conditions.append("Pain")
123
+ if patient_data['Has_Hypertension']: conditions.append("Hypertension")
124
+ if patient_data['Has_Diabetes']: conditions.append("Diabetes")
125
+
126
+ condition_text = ", ".join(conditions) if conditions else "None"
127
+ pdf.cell(190, 5, f"Symptoms: {condition_text}", 1, ln=True)
128
+
129
+ # Diagnosis Section
130
+ pdf.ln(2)
131
+ pdf.set_font("Arial", 'B', 10)
132
+ pdf.cell(190, 6, "Diagnosis", ln=True, border=1)
133
+ pdf.set_font("Arial", '', 9)
134
+
135
+ # Diagnosis information in a more compact format
136
+ pdf.cell(95, 5, f"Condition: {prediction_results.get('Predicted_Disease', 'Not available')}", 1)
137
+ pdf.cell(47.5, 5, f"Risk: {prediction_results.get('Risk_Level', 'N/A')}", 1)
138
+ pdf.cell(47.5, 5, f"Polypharmacy: {prediction_results.get('Polypharmacy_Risk', 'N/A')}", 1, ln=True)
139
+
140
+ if prediction_results.get('Disease_Causes'):
141
+ pdf.set_font("Arial", '', 8)
142
+ # Limit text length to avoid overflow
143
+ causes_text = prediction_results.get('Disease_Causes', '')[:150]
144
+ if len(prediction_results.get('Disease_Causes', '')) > 150:
145
+ causes_text += "..."
146
+ pdf.cell(190, 5, f"Causes: {causes_text}", 1, ln=True)
147
+
148
+ # Medication Section - more compact
149
+ pdf.ln(2)
150
+ pdf.set_font("Arial", 'B', 10)
151
+ pdf.cell(190, 6, "Prescribed Medications", ln=True, border=1)
152
+ pdf.set_font("Arial", '', 8)
153
+
154
+ for i in range(1, 4):
155
+ med_key = f'Medicine_{i}'
156
+ dose_key = f'Dosage_{i}'
157
+ freq_key = f'Frequency_{i}'
158
+ dur_key = f'Duration_{i}'
159
+
160
+ if prediction_results.get(med_key):
161
+ med_name = prediction_results.get(med_key, '')
162
+ dosage = prediction_results.get(dose_key, '')
163
+ frequency = prediction_results.get(freq_key, '')
164
+ duration = prediction_results.get(dur_key, '')
165
+ pdf.cell(60, 5, f"{i}. {med_name}", 1)
166
+ pdf.cell(40, 5, f"Dosage: {dosage}", 1)
167
+ pdf.cell(45, 5, f"Freq: {frequency}", 1)
168
+ pdf.cell(45, 5, f"Duration: {duration}", 1, ln=True)
169
+
170
+ # Instructions and Health Tips - use shorter format
171
+ pdf.ln(2)
172
+ pdf.set_font("Arial", 'B', 10)
173
+ pdf.cell(190, 6, "Instructions & Recommendations", ln=True, border=1)
174
+ pdf.set_font("Arial", '', 8)
175
+
176
+ # Get instruction values
177
+ instr1 = prediction_results.get('Instructions_1', '')
178
+ instr2 = prediction_results.get('Instructions_2', '')
179
+ instr3 = prediction_results.get('Instructions_3', '')
180
+
181
+ # Show instructions in compact format
182
+ if instr1 or instr2 or instr3:
183
+ instr_text = ""
184
+ if instr1: instr_text += f"1. {instr1[:80]}... " if len(instr1) > 80 else f"1. {instr1} "
185
+ if instr2: instr_text += f"2. {instr2[:80]}... " if len(instr2) > 80 else f"2. {instr2} "
186
+ if instr3: instr_text += f"3. {instr3[:80]}... " if len(instr3) > 80 else f"3. {instr3} "
187
+ pdf.multi_cell(190, 5, instr_text, 1)
188
+
189
+ # Health tips (condensed)
190
+ if prediction_results.get('Personalized_Health_Tips'):
191
+ tips = prediction_results.get('Personalized_Health_Tips', '')[:150]
192
+ if len(prediction_results.get('Personalized_Health_Tips', '')) > 150:
193
+ tips += "..."
194
+ pdf.cell(190, 5, f"Health Tips: {tips}", 1, ln=True)
195
+
196
+ # Required Tests Section (condensed)
197
+ if prediction_results.get('Required_Tests'):
198
+ tests = ", ".join(prediction_results.get('Required_Tests', []))
199
+ pdf.cell(190, 5, f"Recommended Tests: {tests}", 1, ln=True)
200
+
201
+ # Add footer with disclaimer
202
+ pdf.set_y(-20)
203
+ pdf.set_font("Arial", 'I', 6)
204
+ pdf.cell(190, 4, "Disclaimer: This is an AI-generated medical prediction and should be reviewed by a healthcare professional.", 0, ln=True, align='C')
205
+ pdf.cell(190, 4, "Not for clinical use without professional medical consultation.", 0, ln=True, align='C')
206
+
207
+ return pdf.output(dest="S").encode("latin1")
208
+
209
+ # Load the trained model and encoders
210
+ @st.cache_resource
211
+ def load_resources():
212
+ # Change paths to load from the current directory
213
+ pipeline = load_model('synthetic_v2_pipeline.joblib')
214
+ target_encoders = joblib.load('synthetic_v2_target_encoders.joblib')
215
+ mappings = joblib.load('synthetic_v2_disease_mappings.joblib')
216
+ return pipeline, target_encoders, mappings
217
+
218
+ pipeline, target_encoders, mappings = load_resources()
219
+
220
+ # Sidebar for app information
221
+ with st.sidebar:
222
+ st.image("https://img.icons8.com/plasticine/100/000000/hospital-3.png", width=100)
223
+ st.markdown("## About")
224
+ st.markdown("This application predicts medical outcomes based on patient data using a machine learning model.")
225
+ st.markdown("### Instructions")
226
+ st.markdown("1. Enter patient information in the form")
227
+ st.markdown("2. Click 'Generate Prediction'")
228
+ st.markdown("3. View the predicted outcome and recommendations")
229
+
230
+ st.markdown("---")
231
+ st.markdown("### 🔍 Model Information")
232
+ st.markdown("Synthetic Medical Outcome Predictor")
233
+ st.markdown("Version: 2.0")
234
+
235
+ # Main content
236
+ st.markdown('<p class="main-header">Medical Outcome Predictor</p>', unsafe_allow_html=True)
237
+
238
+ # Input features in a card with tabs
239
+ with st.container():
240
+ st.markdown('<p class="sub-header">Patient Information</p>', unsafe_allow_html=True)
241
+
242
+ tabs = st.tabs(["Demographics", "Symptoms", "Vital Signs"])
243
+
244
+ with tabs[0]:
245
+ col1, col2 = st.columns(2)
246
+ with col1:
247
+ patient_name = st.text_input("Patient Name", value="")
248
+ age = st.number_input("Age", min_value=0, max_value=120, value=30)
249
+ gender = st.selectbox("Gender", options=["Male", "Female"])
250
+ with col2:
251
+ blood_group = st.selectbox("Blood Group", options=["A+", "A-", "B+", "B-", "O+", "O-", "AB+", "AB-"])
252
+ weight = st.number_input("Weight (kg)", min_value=0.0, value=70.0, step=0.1)
253
+
254
+ with tabs[1]:
255
+ col1, col2 = st.columns(2)
256
+ with col1:
257
+ has_fever = st.checkbox("Has Fever")
258
+ has_cough = st.checkbox("Has Cough")
259
+ has_fatigue = st.checkbox("Has Fatigue")
260
+ with col2:
261
+ has_pain = st.checkbox("Has Pain")
262
+ has_hypertension = st.checkbox("Has Hypertension")
263
+ has_diabetes = st.checkbox("Has Diabetes")
264
+
265
+ with tabs[2]:
266
+ col1, col2 = st.columns(2)
267
+ with col1:
268
+ temperature = st.number_input("Temperature (°C)", min_value=30.0, max_value=42.0, value=37.0, step=0.1)
269
+ heart_rate = st.number_input("Heart Rate", min_value=30, max_value=200, value=70)
270
+ bp_systolic = st.number_input("Blood Pressure (Systolic)", min_value=50, max_value=200, value=120)
271
+ with col2:
272
+ wbc_count = st.number_input("WBC Count", min_value=0.0, value=7.0, step=0.1)
273
+ glucose_level = st.number_input("Glucose Level", min_value=0.0, value=90.0, step=0.1)
274
+
275
+ # Prepare input data for prediction
276
+ input_data = {
277
+ 'Patient_Name': patient_name,
278
+ 'Age': age,
279
+ 'Gender': gender,
280
+ 'Blood_Group': blood_group,
281
+ 'Weight_kg': weight,
282
+ 'Has_Fever': int(has_fever),
283
+ 'Has_Cough': int(has_cough),
284
+ 'Has_Fatigue': int(has_fatigue),
285
+ 'Has_Pain': int(has_pain),
286
+ 'Has_Hypertension': int(has_hypertension),
287
+ 'Has_Diabetes': int(has_diabetes),
288
+ 'Temperature_C': temperature,
289
+ 'Heart_Rate': heart_rate,
290
+ 'BP_Systolic': bp_systolic,
291
+ 'WBC_Count': wbc_count,
292
+ 'Glucose_Level': glucose_level
293
+ }
294
+
295
+ # Define the order of input features
296
+ input_feature_names = [
297
+ 'Patient_Name', 'Age', 'Gender', 'Blood_Group', 'Weight_kg',
298
+ 'Has_Fever', 'Has_Cough', 'Has_Fatigue', 'Has_Pain',
299
+ 'Has_Hypertension', 'Has_Diabetes', 'Temperature_C',
300
+ 'Heart_Rate', 'BP_Systolic', 'WBC_Count', 'Glucose_Level'
301
+ ]
302
+
303
+ # Button to make predictions with a progress indicator
304
+ st.markdown('<div class="section-divider"></div>', unsafe_allow_html=True)
305
+ col1, col2, col3 = st.columns([1, 2, 1])
306
+ with col2:
307
+ predict_button = st.button("Generate Prediction", type="primary", use_container_width=True)
308
+
309
+ if predict_button:
310
+ with st.spinner("Analyzing patient data..."):
311
+ # Prepare feature values in the correct order
312
+ feature_values = [input_data[name] for name in input_feature_names]
313
+ encoded_input = encode_input_features(input_feature_names, feature_values)
314
+
315
+ # Make predictions using the pipeline's predict function
316
+ predictions_array = pipeline.predict(encoded_input)
317
+
318
+ # Define the output columns that our model predicts
319
+ target_columns = [
320
+ 'Predicted_Disease', 'Medicine_1', 'Dosage_1', 'Frequency_1', 'Duration_1',
321
+ 'Medicine_2', 'Dosage_2', 'Frequency_2', 'Duration_2',
322
+ 'Medicine_3', 'Dosage_3', 'Frequency_3', 'Duration_3',
323
+ 'Polypharmacy_Risk'
324
+ ]
325
+
326
+ # Convert predictions array to DataFrame
327
+ predictions_encoded = pd.DataFrame(predictions_array, columns=target_columns)
328
+
329
+ # Decode the predictions using target_encoders
330
+ predictions_decoded = {}
331
+ for col in predictions_encoded.columns:
332
+ encoder = target_encoders.get(col)
333
+ if encoder:
334
+ predictions_decoded[col] = encoder.inverse_transform([predictions_encoded[col].iloc[0]])[0]
335
+ else:
336
+ predictions_decoded[col] = predictions_encoded[col].iloc[0]
337
+
338
+ # Get mapping outputs based on the predicted disease
339
+ predicted_disease = predictions_decoded.get('Predicted_Disease')
340
+ mapping_outputs = get_mapped_outputs(predicted_disease, mappings)
341
+
342
+ # Combine prediction outputs and mapping outputs into a single dictionary
343
+ final_output = {**predictions_decoded, **mapping_outputs}
344
+
345
+ # Display the prediction results in a more visually appealing way
346
+ st.markdown('<p class="prediction-header">Diagnosis & Treatment Plan</p>', unsafe_allow_html=True)
347
+
348
+ col1, col2 = st.columns([1, 2])
349
+
350
+ with col1:
351
+ st.markdown('<div class="card">', unsafe_allow_html=True)
352
+ st.markdown(f"### Diagnosis")
353
+ st.markdown(f"**Condition:** {final_output.get('Predicted_Disease', 'Not available')}")
354
+ st.markdown(f"**Risk Level:** {mapping_outputs.get('Risk_Level', 'Not available')}")
355
+ st.markdown(f"**Polypharmacy Risk:** {final_output.get('Polypharmacy_Risk', 'Not available')}")
356
+
357
+ # Add Disease Causes
358
+ if final_output.get('Disease_Causes'):
359
+ st.markdown("### Disease Causes")
360
+ st.markdown(f"{final_output.get('Disease_Causes', 'Not available')}")
361
+ st.markdown('</div>', unsafe_allow_html=True)
362
+
363
+ if 'Required_Tests' in mapping_outputs:
364
+ st.markdown('<div class="card">', unsafe_allow_html=True)
365
+ st.markdown("### Recommended Tests")
366
+ for test in mapping_outputs.get('Required_Tests', []):
367
+ st.markdown(f"- {test}")
368
+ st.markdown('</div>', unsafe_allow_html=True)
369
+
370
+ with col2:
371
+ st.markdown('<div class="card">', unsafe_allow_html=True)
372
+ st.markdown("### Prescribed Medications")
373
+
374
+ if final_output.get('Medicine_1'):
375
+ st.markdown(f"**1. {final_output.get('Medicine_1', '')}**")
376
+ st.markdown(f" - Dosage: {final_output.get('Dosage_1', '')}")
377
+ st.markdown(f" - Frequency: {final_output.get('Frequency_1', '')}")
378
+ st.markdown(f" - Duration: {final_output.get('Duration_1', '')}")
379
+
380
+ if final_output.get('Medicine_2'):
381
+ st.markdown(f"**2. {final_output.get('Medicine_2', '')}**")
382
+ st.markdown(f" - Dosage: {final_output.get('Dosage_2', '')}")
383
+ st.markdown(f" - Frequency: {final_output.get('Frequency_2', '')}")
384
+ st.markdown(f" - Duration: {final_output.get('Duration_2', '')}")
385
+
386
+ if final_output.get('Medicine_3'):
387
+ st.markdown(f"**3. {final_output.get('Medicine_3', '')}**")
388
+ st.markdown(f" - Dosage: {final_output.get('Dosage_3', '')}")
389
+ st.markdown(f" - Frequency: {final_output.get('Frequency_3', '')}")
390
+ st.markdown(f" - Duration: {final_output.get('Duration_3', '')}")
391
+ st.markdown('</div>', unsafe_allow_html=True)
392
+
393
+ # New card for specific instructions
394
+ st.markdown('<div class="card">', unsafe_allow_html=True)
395
+ st.markdown("### Specific Instructions")
396
+
397
+ col1, col2, col3 = st.columns(3)
398
+ with col1:
399
+ if final_output.get('Instructions_1'):
400
+ st.markdown(f"**Instruction 1:**")
401
+ st.markdown(f"{final_output.get('Instructions_1', 'None')}")
402
+ with col2:
403
+ if final_output.get('Instructions_2'):
404
+ st.markdown(f"**Instruction 2:**")
405
+ st.markdown(f"{final_output.get('Instructions_2', 'None')}")
406
+ with col3:
407
+ if final_output.get('Instructions_3'):
408
+ st.markdown(f"**Instruction 3:**")
409
+ st.markdown(f"{final_output.get('Instructions_3', 'None')}")
410
+ st.markdown('</div>', unsafe_allow_html=True)
411
+
412
+ # Additional information in expanders
413
+ with st.expander("Personalized Health Tips"):
414
+ if final_output.get('Personalized_Health_Tips'):
415
+ st.markdown(f"{final_output.get('Personalized_Health_Tips')}")
416
+ else:
417
+ st.write("No personalized health tips available.")
418
+
419
+ with st.expander("Polypharmacy Recommendation"):
420
+ if final_output.get('Polypharmacy_Recommendation'):
421
+ st.markdown(f"{final_output.get('Polypharmacy_Recommendation')}")
422
+ else:
423
+ st.write("No polypharmacy recommendations available.")
424
+
425
+ # Raw JSON output for reference (collapsed by default)
426
+ with st.expander("View Raw Prediction Data"):
427
+ st.json(final_output)
428
+
429
+ # Add PDF download section with a visual separator
430
+ st.markdown('<hr style="margin-top: 30px; margin-bottom: 30px;">', unsafe_allow_html=True)
431
+
432
+ # Create a centered container for the download button
433
+ col1, col2, col3 = st.columns([1, 2, 1])
434
+ with col2:
435
+ st.markdown("### 📄 Download Complete Medical Report")
436
+ st.markdown("Get a professionally formatted medical report with all diagnosis and treatment details.")
437
+
438
+ # Generate PDF report
439
+ pdf_bytes = generate_pdf_report(input_data, final_output)
440
+
441
+ # Create download button
442
+ patient_name_safe = patient_name.replace(" ", "_") if patient_name else "Patient"
443
+ st.download_button(
444
+ label="Download Medical Report (PDF)",
445
+ data=pdf_bytes,
446
+ file_name=f"Medical_Report_{patient_name_safe}_{datetime.now().strftime('%Y%m%d')}.pdf",
447
+ mime="application/pdf",
448
+ use_container_width=True,
449
+ )
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ pandas
3
+ numpy
4
+ joblib
5
+ scikit-learn
6
+ lightgbm
7
+ plotly
8
+ streamlit-card
9
+ fpdf
synthetic_v2_disease_mappings.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bd569bb375c31fdf8882aedb2b71b8995dd95682db82a603f3419221d194412a
3
+ size 4184
synthetic_v2_pipeline.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5a20461a135a3dbfc6d5ee36f0f01a6b9be43b24bb14f12b17ee15ba3da5a87f
3
+ size 65824674
synthetic_v2_target_encoders.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:30f86ca168310c108aecadfbc5dfbbedc2904ccb46c141f7b3cfec6d81babf0f
3
+ size 5771