MINDSETS-APP / Classification.py
Salma Hassan
Implement code changes to enhance functionality and improve performance
a30d5f6
Raw
History Blame Contribute Delete
13.1 kB
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('<p style="color:orange;">[Step 1/3] Running Segmentation model...</p>', 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'<p style="color:orange;">[Step 2/3] Extracting Radiomics...</p>', 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'<p style="color:orange;">[Step 3/3] Classification in progress...</p>', 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'<p style="color:green;">Classification completed successfully in {int(time_taken)} seconds!</p>', unsafe_allow_html=True)
# st.write(label)