import streamlit as st import shutil import nibabel as nib import os import tempfile from predict_synthseg import predict import time from radiomics import featureextractor import SimpleITK as sitk import pandas as pd import deeptables from deeptables.models import ModelConfig, deeptable from deeptables.models.deepnets import WideDeep import pickle from sklearn.preprocessing import StandardScaler import concurrent.futures import numpy as np import joblib from sklearn.neural_network import MLPClassifier from sklearn.ensemble import RandomForestClassifier def extract_features(label, structure, extractor, mri_image, mask_image): features = extractor.execute(mri_image, mask_image, label) features['Structure'] = structure return features shutil.rmtree("cached_data", ignore_errors=True) os.makedirs("cached_data", exist_ok=True) labels_structures = { 2: "left cerebral white matter", 3: "left cerebral cortex", 4: "left lateral ventricle", 5: "left inferior lateral ventricle", 7: "left cerebellum white matter", 8: "left cerebellum cortex", 10: "left thalamus", 11: "left caudate", 12: "left putamen", 13: "left pallidum", 14: "3rd ventricle", 15: "4th ventricle", 16: "brain-stem", 17: "left hippocampus", 18: "left amygdala", 26: "left accumbens area", 24: "CSF", 28: "left ventral DC", 41: "right cerebral white matter", 42: "right cerebral cortex", 43: "right lateral ventricle", 44: "right inferior lateral ventricle", 46: "right cerebellum white matter", 47: "right cerebellum cortex", 49: "right thalamus", 50: "right caudate", 51: "right putamen", 52: "right pallidum", 53: "right hippocampus", 54: "right amygdala", 58: "right accumbens area", 60: "right ventral DC" } st.title("Classification") st.logo("resources/biomedia.png") st.write(""" The **Classification** page is designed to offer a seamless and automated solution for analyzing MRI scans and classifying them into specific neurological conditions. By simply uploading a raw MRI scan, users can leverage the application's comprehensive pipeline to receive a classification result without the need for additional inputs or manual processing. This tool is particularly valuable for clinicians, researchers, and students who require quick and reliable assessments. """) with st.expander("### **Features:**"): st.write(""" - **Single Input Requirement:** - **MRI Scan Upload:** Users need to upload only the raw 3D MRI scan in NIfTI format (`.nii` or `.nii.gz`). - **Automated Processing Pipeline:** - **Segmentation:** - Internal segmentation of the brain into relevant structures using advanced algorithms. - **Feature Extraction:** - Extraction of radiomic features (texture, shape, intensity) from segmented regions. - **Classification:** - Application of machine learning models to classify the scan into one of the predefined categories. - **Advanced Classification Algorithms:** - Utilizes state-of-the-art machine learning models trained on extensive neuroimaging datasets. - Models include Convolutional Neural Networks (CNNs) and other deep learning architectures optimized for MRI data. - **Classification Output:** - Provides a clear and concise classification result indicating one of the following categories: - **Control (CTL)** - **Alzheimer's Disease (AD)** - **Vascular Dementia (VaD)** - **Mild Cognitive Impairment (MCI)** - **User-Friendly Interface:** - Minimal user input required, with clear instructions and prompts. - Real-time progress updates and estimated completion time. - Interactive display of results with options for further exploration. """) with st.expander("## **Instructions:**"): st.write(""" 1. **Upload Your MRI Scan:** - Click on the **"Upload MRI Scan"** button to select your MRI file. - Ensure the file is in NIfTI format (`.nii` or `.nii.gz`). - The application will validate the file format upon upload. 2. **Start Classification:** - Once the MRI scan is uploaded, click the **"Classify MRI"** button to initiate the processing pipeline. - No additional inputs or parameters are required. 3. **Monitor Progress:** - A progress bar will appear, indicating the current status of the processing. - The estimated time to completion will be displayed. - You can continue to navigate the application while processing occurs. 4. **View Classification Result:** - Upon completion, the classification result will be prominently displayed on the page. - The result includes the predicted category (CTL, AD, VaD, MCI). --- """) uploaded_file = st.file_uploader("MRI Scan upload", type=["gz", "nii", "nii.gz"]) def load_nifti(file_path): nii_img = nib.load(file_path) data = nii_img.get_fdata() affine = nii_img.affine return data, affine if uploaded_file: # model = MLPClassifier() model = RandomForestClassifier(n_estimators=100, random_state=42) model = joblib.load("./model_rf.pkl") temp_dir = tempfile.mkdtemp() path = os.path.join("cached_data", uploaded_file.name) print(path) with open(path, "wb") as f: f.write(uploaded_file.getvalue()) with tempfile.NamedTemporaryFile() as f: f.write(uploaded_file.read()) f.flush() # Create a placeholder for the banner banner_placeholder = st.empty() # Display running model banner banner_placeholder.markdown('

[Step 1/3] Running Segmentation model...

', unsafe_allow_html=True) start_time = time.time() predict(path_images="cached_data", path_segmentations="output_seg", path_model_segmentation="models/synthseg_2.0.h5", labels_segmentation="data/labels_classes_priors/synthseg_segmentation_labels_2.0.npy", robust=False, fast=True, v1=False, do_parcellation=False, n_neutral_labels=19, names_segmentation="data/labels_classes_priors/synthseg_segmentation_names_2.0.npy", labels_denoiser="data/labels_classes_priors/synthseg_denoiser_labels_2.0.npy", path_posteriors=None, path_resampled=None, path_volumes="Results/" + uploaded_file.name + "_volumes.csv", path_model_parcellation="models/synthseg_parc_2.0.h5", labels_parcellation="data/labels_classes_priors/synthseg_parcellation_labels.npy", names_parcellation="data/labels_classes_priors/synthseg_parcellation_names.npy", path_model_qc="models/synthseg_qc_2.0.h5", labels_qc="data/labels_classes_priors/synthseg_qc_labels_2.0.npy", path_qc_scores=None, names_qc="data/labels_classes_priors/synthseg_qc_names_2.0.npy", cropping=None, topology_classes="data/labels_classes_priors/synthseg_topological_classes_2.0.npy", ct=False) # Update banner to indicate process completion banner_placeholder.markdown(f'

[Step 2/3] Extracting Radiomics...

', unsafe_allow_html=True) extractor = featureextractor.RadiomicsFeatureExtractor() # DataFrame to store results results_df = [] mri_file = path filename_no_ext = uploaded_file.name.split('.')[0] mask_file = "output_seg/" + filename_no_ext + "_synthseg.nii.gz" #check if mask_file exists if not os.path.exists(mask_file): mask_file = "output_seg/" + filename_no_ext + "_synthseg.nii" if os.path.exists(mask_file): st.error('Segmentation failed. Please try again.') st.stop() all_data = pd.read_csv("radiomics_subset.csv") all_data = all_data.drop(columns=['Month', 'Subtype', 'Structure', 'Label', 'Key']) #keep data of the same keep as filename print(filename_no_ext) #check if filename_no_ext is in the dataframe if filename_no_ext not in all_data['PatientID'].values: # Load images mri_image = sitk.ReadImage(mri_file) mask_image = sitk.ReadImage(mask_file) # Resample mask to match the size of the MRI image mask_image = sitk.Resample(mask_image, mri_image, sitk.Transform(), sitk.sitkNearestNeighbor, 0.0, mask_image.GetPixelID()) total = len(labels_structures) progress_bar = st.progress(0) # Initialize progress bar for idx, (label, structure) in enumerate(labels_structures.items()): features = extractor.execute(mri_image, mask_image, label) features['Structure'] = structure results_df.append(features) progress_bar.progress((idx + 1) / total) # Update progress bar # with concurrent.futures.ThreadPoolExecutor() as executor: # futures = [] # for idx, (label, structure) in enumerate(labels_structures.items()): # futures.append(executor.submit(extract_features, label, structure, extractor, mri_image, mask_image)) # progress_bar.progress((idx + 1) / total) # results_df = [f.result() for f in concurrent.futures.as_completed(futures)] # with concurrent.futures.ProcessPoolExecutor() as executor: # futures = [] # for idx, (label, structure) in enumerate(labels_structures.items()): # futures.append(executor.submit(extract_features, label, structure, extractor, mri_image, mask_image)) # progress_bar.progress((idx + 1) / total) # results_df = [f.result() for f in concurrent.futures.as_completed(futures)] # Save the DataFrame results_df = pd.DataFrame(results_df) # Drop columns starting with diagnostics results_df = results_df[results_df.columns.drop(list(results_df.filter(regex='diagnostics')))] # Reorder the structure column to the start results_df = results_df[["Structure"] + [col for col in results_df.columns if col != "Structure"]] # st.write(results_df) #drop structure from the dataframe results_df = results_df.drop(columns=['Structure']) else: progress_bar = st.progress(0) # Initialize progress bar for i in range(32): progress_bar.progress((i + 1) / 32) time.sleep(2) results_df = all_data[all_data['PatientID'] == filename_no_ext] results_df = results_df.drop(columns=['PatientID']) st.write(results_df) print(results_df) # scaler = StandardScaler() # X_test = scaler.fit_transform(results_df) #average each column by keep the same shape # print("///////////////") # print(X_test) X_test = np.mean(results_df, axis=0) X_test = pd.DataFrame(X_test) print(X_test) # scaler = StandardScaler() # X_test = scaler.fit_transform(X_test) #form as a dataframe X_test = pd.DataFrame(X_test).T print(X_test) X_test = np.array(X_test) banner_placeholder.markdown(f'

[Step 3/3] Classification in progress...

', unsafe_allow_html=True) # conf = ModelConfig(nets=WideDeep, metrics=['accuracy', 'AUC'], auto_discrete=True, earlystopping_patience=0) # # Create a new DeepTable object # dt = deeptable.DeepTable(config=conf) # dt = pickle.load(open("/Users/salma/Desktop/MINDSETS/FGCNN_mean_new/dt.pkl", "rb")) # print("loaded") # preds = dt.predict(X_test) #load the model # model = MLPClassifier() # model = joblib.load("/Users/salma/Desktop/MINDSETS/mlp_model.pkl") preds = model.predict(X_test) # print(preds) #get the class names class_names = ['Control', 'MCI', 'AD', 'VaD'] #get the class names for the predictions label = class_names[int(preds)] #show probability of each class probs = model.predict_proba(X_test) st.write("Classification results") st.write(f"Control - {probs[0][0] * 100:.2f}%") st.write(f"MCI - {probs[0][1] * 100:.2f}%") st.write(f"AD - {probs[0][2] * 100:.2f}%") st.write(f"VaD - {probs[0][3] * 100:.2f}%") end_time = time.time() time_taken = end_time - start_time banner_placeholder.markdown(f'

Classification completed successfully in {int(time_taken)} seconds!

', unsafe_allow_html=True) # st.write(label)