deepthiaj/Electro_oneAPI
3
1import streamlit as st2import pandas as pd 3import pickle4import xgboost as xgb5import numpy as np6import sklearn 7from sklearn.metrics import confusion_matrix, classification_report8import seaborn as sns9import matplotlib.pyplot as plt10# from streamlit_pandas_profiling import st_profile_report11# from st_aggrid import AgGrid12from io import StringIO13from scipy import signal14import ecg_plot15import daal4py as d4p16 17st.title("Automated Diagnosis of Heart Disease from Electro-Cardiogram")18st.write('This is a prototype for checking heart health condition. The performance of the model has been achieved using XGboost ML algorithm.')19st.write('Please select the data and the model from the dropdown menu on the left panel to see the working of this prototype.')20 21st.divider()22 23enc_dat = pd.read_csv("PTB_ECGencoded_dat.csv")24 25# Split the dataset into features (X) and target (y)26X = enc_dat.iloc[:, :-1].values # Features (all columns except the last one)27y = enc_dat.iloc[:, -1].values # Target (last column "diagnosis")28# Map the existing class labels to the expected class values29class_mapping = {0: 0, 1: 1, 3: 2, 4: 3, 6: 4, 7: 5}30mapped_labels = np.array([class_mapping[label] for label in y])31 32# Define the model parameters33model_params = {34 'objective': 'multi:softmax',35# 'num_class': 10,36 'num_class': 6, # Adjust the number of classes accordingly37 'random_state': 4238}39 40# Create and train the XGBoost model41xgb_model = xgb.XGBClassifier(**model_params)42# xgb_model.fit(X, y)43xgb_model.fit(X, mapped_labels)44 45 46 47 48daal_model = d4p.get_gbt_model_from_xgboost(xgb_model.get_booster())49 50 51 52 53 54 55 56# # Train an XGBoost model57# params = {58# 'objective': 'multi:softmax',59# 'num_class': 10,60# 'random_state': 4261# }62 63# xgb_model = xgb.XGBClassifier(**params)64# xgb_model.fit(X, y)65 66 67# test_data = pd.read_csv("PTB_ECGencoded_dat.csv")68# X_test = test_data.iloc[:, :-1].values69# y_test = test_data.iloc[:, -1].values70# # Map the existing class labels to the expected class values71# class_mapping = {0: 0, 1: 1, 3: 2, 4: 3, 6: 4, 7: 5}72# mapped_labels = np.array([class_mapping[label] for label in y_])73# Choose a test data point74# ecg_test_data = X_test[0] 75 76 77 78 79 80st.subheader("Performance evaluation of the Automated Diagnosis Model")81 82 83if st.button('ECG analysis of Patient001'):84 # patient001_signal_analysis() to visualize data analysis of single patient upon a button click85 st.write('give plots and heart rate analysis. Please upload ECG signal data in specified format below for analysis')86 # refer PTB website for format87 # call preprocessing module88 # call ecg_analysis()89 90st.divider()91 # # Evaluate the model on the entire dataset92y_pred = xgb_model.predict(X)93accuracy = np.sum(y_pred == mapped_labels) / len(mapped_labels) # Calculate accuracy94 # print(f"Accuracy: {accuracy}")95acc = (accuracy / 1) * 10096st.write("The accuracy of the diagnosis report is: ", acc, "%")97 98 99# Make a faster prediction with oneDAL100daal_prediction = d4p.gbt_classification_prediction(nClasses = n_classes).compute(X_test, daal_model).prediction101 102# # List all results that you need by placing '|' between them103# predict_algo = d4p.104# gbt_classification_prediction(nClasses = n_classes,105# resultsToEvaluate = "computeClassLabels|computeClassProbabilities")106# daal_prediction = predict_algo.compute(X_test, model)107# # Get probabilities:108# probabilities = daal_prediction.probabilities109# # Get labels:110# labels = daal_prediction.prediction111 112st.divider()113 114 # # Evaluate the model on the entire dataset115 # y_pred = loaded_model.predict(X)116 117 # # Calculate evaluation metrics118classification_metrics = classification_report(mapped_labels, y_pred, output_dict=True)119st.caption(":blue[Classification Metrics]")120# classification_metrics = [classification_metrics]121# cm = classification_metrics.insert(0,'metrics')122st.table(classification_metrics)123# st.json(classification_metrics)124st.write("1: Myocardial infarction, 2: Bundle branch block, 3: Dysrhythmia , 4: Valvular heart disease, 5: Myocarditis")125 126st.divider()127 # # Calculate confusion matrix128confusion_mat = confusion_matrix(mapped_labels, y_pred)129# st.write("Confusion matrix:")130 131 # # Plot confusion matrix132plt.figure(figsize=(10, 8))133htmap = sns.heatmap(confusion_mat, annot=True, fmt="d", cmap="Blues")134plt.title("Confusion Matrix")135plt.xlabel("Predicted Class")136plt.ylabel("True Class")137plt.show()138htmap = htmap.figure139st.pyplot(htmap)140 141 142st.divider()143 # Format signal info & preprocessing module for generating X[0] to diagnose from an external input data & give a dropbox to enter a single patient ecg data in .dat and .hea format144 145 146 147 148 149 150patient_enc_data = {"Patient001":X[0],"Patient002":X[100],"Patient003":X[200],"Patient004":X[50],"Patient005":X[40],"Patient006":X[30],"Patient007":X[20],"Patient008":X[10],"Patient009":X[60],"Patient010":X[110],"Patient011":X[120],"Patient012":X[130],"Patient013":X[140],"Patient014":X[150],"Patient015":X[160],"Patient016":X[170],"Patient017":X[180],"Patient018":X[190],"Patient019":X[210],"Patient020":X[220],"Patient021":X[21],"Patient022":X[22],"Patient023":X[23],"Patient024":X[24],"Patient025":X[25],"Patient026":X[26],"Patient027":X[27],"Patient028":X[28],"Patient029":X[29],"Patient030":X[31],"Patient031":X[41],"Patient032":X[42],"Patient033":X[43],"Patient034":X[44],"Patient035":X[45],"Patient036":X[46],"Patient037":X[47],"Patient038":X[48],"Patient039":X[49],"Patient040":X[51],"Patient41":X[61],"Patient042":X[62],"Patient043":X[63],"Patient044":X[64],"Patient045":X[65],"Patient046":X[66],"Patient047":X[67],"Patient048":X[68],"Patient049":X[69],"Patient050":X[71], }151patient_ecg_sel = st.selectbox( "Select a ECG of a patient from the list", list(patient_enc_data.keys()))152 153 154 155 156def ecg_analysis(ecg_test_data):157 158 # Classify the test data point159 predicted_class = xgb_model.predict(np.array([ecg_test_data]))160 161 162 st.subheader("Diagnosis Report")163 # Define the mapping of diagnosis labels to numerical values164 # diagnosis_mapping = {165 # "Myocardial infarction": 1,166 # "Cardiomyopathy/Heart failure": 2,167 # "Bundle branch block": 3,168 # "Dysrhythmia": 4,169 # "Myocardial hypertrophy": 5,170 # "Valvular heart disease": 6,171 # "Myocarditis": 7,172 # "Miscellaneous": 8,173 # "Healthy controls": 9174 # }175 176 if predicted_class[0] == 0:177 st.write("Sorry, We cannot give your diagnosis report at the moment. Kindly consult a doctor in person.")178 elif predicted_class[0] == 1:179 st.write("You are diagnosed with Myocardial infarction.")180 st.write("Kindly consult a doctor to take the necessary treatment.")181 elif predicted_class[0] == 2:182 st.write("You are diagnosed with Bundle branch block.")183 st.write("Kindly consult a doctor to take the necessary treatment.")184 elif predicted_class[0] == 3:185 st.write("You are diagnosed with Dysrhythmia.")186 st.write("Kindly take consult a doctor to the necessary treatment.")187 elif predicted_class[0] == 4:188 st.write("You are diagnosed with Valvular heart disease.") 189 st.write("Kindly consult a doctor to take the necessary treatment.")190 elif predicted_class[0] == 5:191 st.write("You are diagnosed with Myocarditis.") 192 st.write("Kindly consult a doctor to take the necessary treatment.")193 else:194 st.write("Sorry, We cannot give your diagnosis report at the moment. Kindly consult a doctor in person.")195 196 197 198if st.button("Analyze Raw ECG"):199# # if new_data:200# # new_patient_data_preprocessing()201# # else:202 ecg_train_dat = pd.read_csv("PTB_ECGdata.csv")203# # AgGrid(ecg_train_dat)204# # pr = ecg_train_dat.profile_report()205# # st_profile_report(pr)206# # st.write('To be updated!')207# # Count the occurrences of each unique value in the "diagnosis" column208 diagnosis_counts = ecg_train_dat["diagnosis"].value_counts()209 210# # Create a bar plot211# plot0 = plt.bar(diagnosis_counts.index, diagnosis_counts)212 213# # Rotate x-axis labels for better readability214# plt.xticks(rotation=65)215 216# # Add labels and title217# plt.xlabel("Diagnosis")218# plt.ylabel("Count")219# plt.title("Distribution of Diagnosis")220 221# # Adjust layout to prevent overlapping of labels222# plt.tight_layout()223 224# # Display the chart225# plt.show()226# st.pyplot(plot0)227 st.bar_chart(diagnosis_counts)228 229def new_patient_data_preprocessing(new_data):230 231 # code to preprocess .dat and .hea files from PTB ecg database, check one from ptb xl as external new data & convert it into .csv & encode to pass it as an argument to call ecg_analysis function232 st.write('')233 234 235def single_patient_signal_analysis(csv_path):236 df = pd.read_csv(csv_path)237# print(df.keys(), df.shape)238 239 # ecg_plot.plot(df, sample_rate = 500, title='ECG')240 #ecg_plot.save_as_png('ecg','ecg_plots/')241 242 # Plot ECG waveform243 plt.figure(figsize=(12, 4))244 p0 = plt.plot(df["i"])245 plt.title("ECG Waveform")246 plt.xlabel("Sample Number")247 plt.ylabel("Amplitude (mV)")248 plt.show()249 #p0=p0.figure250 #st.pyplot(p0)251 #st.write(p0)252 253 # Calculate and plot PSD of ECG waveform254 f, Pxx = signal.welch(df["i"], fs=360, nperseg=1024)255 plt.figure(figsize=(12, 4))256 p1=plt.plot(f, Pxx)257 plt.title("Power Spectral Density (PSD) of ECG Waveform")258 plt.xlabel("Frequency (Hz)")259 plt.ylabel("PSD")260 plt.show()261 #p1 =p1.figure262 #st.pyplot(p1)263 264 # Calculate heart rate (HR)265 qrs_peaks, _ = signal.find_peaks(df["i"], height=0.5)266 duration = len(df) / 360 # total duration of recording in seconds267 hr = len(qrs_peaks) / duration268 st.write("Heart Rate:", hr, "bpm")269 st.write("The patient has been diagnosed with ",df.loc[0]["diagnosis"])270 271 # Calculate mean and standard deviation of RR interval272 rr_intervals = [qrs_peaks[i] - qrs_peaks[i-1] for i in range(1, len(qrs_peaks))]273 mean_rr = sum(rr_intervals) / len(rr_intervals) / 360 # convert to seconds274 std_rr = (sum((rr - mean_rr*360)**2 for rr in rr_intervals) / (len(rr_intervals) - 1) / 360)**0.5 # convert to seconds275 st.write("Mean RR Interval:",nmean_rr, "s")276 st.write("Standard Deviation of RR Interval:",nstd_rr ,"s")277 278 # Calculate mean and standard deviation of QRS amplitude279 mean_qrs_amp = df.loc[qrs_peaks, "i"].mean()280 std_qrs_amp = df.loc[qrs_peaks, "i"].std()281 st.write("Mean QRS Amplitude:", mean_qrs_amp, "mV")282 st.write("Standard Deviation of QRS Amplitude:", std_qrs_amp, "mV" )283 284 285 286 287# st.write("")288# uploaded_file = st.file_uploader("Upload ECG file")289# if uploaded_file is not None:290 291# # Can be used wherever a "file-like" object is accepted:292# dataframe = pd.read_csv(uploaded_file)293# st.write(dataframe)294 295if st.button("Check Heart health"):296 ecg_test_data = patient_enc_data[patient_ecg_sel]297 st.write("Diagnosis report of", patient_ecg_sel)298 # st_profile_report(ecg_test_data)299 ecg_analysis(ecg_test_data)300else:301 st.write("Diagnosis report of Patient001")302 ecg_test_data = X[0] 303 ecg_analysis(ecg_test_data)304 305 306 307 308if st.button('Signal Analysis of Single Patient ECG'):309 single_patient_signal_analysis("s0010_re.csv")310 311 312 313 