import os
import ants
import monai
import torch
import shutil
import numpy as np
import pandas as pd
import altair as alt
import nibabel as nib
import streamlit as st
from random import randint
from itertools import chain
import antspynet as antspynet
from torch.utils.data import DataLoader
from monai.transforms import Compose, LoadImaged
from monai.networks.nets.efficientnet import EfficientNetBN
import dicom2nifti
st.set_option('deprecation.showPyplotGlobalUse', False)
np.random.seed(0)
torch.manual_seed(0)
template = ants.image_read('MNI152_T1_1mm_brain.nii.gz')
def pre_process(image):
with st.spinner('Reading the image...'):
y = ants.image_read(image)
with st.spinner('Bias field correction ongoing...'):
y = ants.utils.n4_bias_field_correction(y)
with st.spinner('Denoising the image...'):
yn = y + np.random.randn(*y.shape).astype('float32')*5
y = ants.denoise_image(yn, ants.get_mask(y))
with st.spinner('brain_extraction fn. running...'):
x = antspynet.utilities.brain_extraction(
y, modality='t1', antsxnet_cache_directory=None, verbose=True)
y = y*x
with st.spinner('Registering from template..'):
y1 = ants.registration(fixed=template, moving=y,
type_of_transform='AffineFast')
with st.spinner('Applying transforms...'):
y = ants.apply_transforms(
fixed=template, moving=y, transformlist=y1['fwdtransforms'])
st.success('Successfully Preprocessed the Image !')
return y
col1, col2, col3 = st.columns(3)
with col1:
st.write(' ')
with col2:
st.image("unilogo.png")
with col3:
st.write(' ')
st.markdown("
Deep-AD: Deep Learning Model for Early Detection of Alzheimer’s
", unsafe_allow_html=True)
st.markdown("Developed by: Deevyankar Agarwal
",
unsafe_allow_html=True)
st.markdown(" Part Time Ph.D. Student, UVA, Spain
",
unsafe_allow_html=True)
st.write('**Description**: Users can upload T1-W MRIs either in NifTI or DICOM format. After preprocessing (N4 bias field correction, noise removal, brain extraction, and registration in the MNI-152 template), the model will classify MRI scans into one of three groups.')
st.markdown('- AD : Alzheimer’s')
st.markdown('- CN : Cognitively Normal')
st.markdown('- SMCI : stable MCI')
st.write('This Application is based on ensemble learning. The output of multiclassification task AD vs. sMCI vs. CN will be validated further by binary classification models AD vs. CN and sMCI vs. AD implemented by end-to-end learning and 3D transfer learning, respectively. It will provide an extra layer of verification to make robust decisions.')
st.markdown('''
''', unsafe_allow_html=True)
element1 = st.write("""
# MRI Classification :brain:
"""
)
if 'key' not in st.session_state:
st.session_state.key = str( randint(1000, 100000000))
file_upload = st.file_uploader("Upload the MRI scan (either a single NIfTI file or a folder containing multiple DICOM files)", type=[
"nii", "gz", "dcm"], accept_multiple_files=True, key=st.session_state.key)
st.set_option('deprecation.showfileUploaderEncoding', False)
if file_upload == []:
st.text("No file uploaded !")
st.text('Note : Please clear existing files before uploading new files')
if st.button('Clear Uploaded File(s)', help='Please clear existing files before uploading new files') and 'key' in st.session_state.keys():
st.session_state.pop('key')
st.experimental_rerun()
st.write("⚠️ [**Feedback form**](https://forms.gle/xuScGN6Cmf69bsUE9) ⚠️ ")
if len(file_upload) == 1:
for file in file_upload:
file.name = file.name
with open(file.name, "wb") as f:
f.write(file.getbuffer())
saved_path = f"{file.name}"
display_image = ants.image_read(saved_path)
element2 = st.pyplot(ants.plot(display_image))
processed_image = pre_process(saved_path)
a = processed_image.to_nibabel()
saved_preprocessed_path = 'input_image'
nib.save(a, saved_preprocessed_path)
element3 = st.text("Preprocessed Image")
element4 = st.pyplot(ants.plot(f"{saved_preprocessed_path}.nii", cmap="seismic"))
transformsv = Compose(
[
LoadImaged(keys=["img"])
]
)
test_files = [{"img": f"{saved_preprocessed_path}.nii", "label": "NA"}]
test_ds = monai.data.Dataset(data=test_files, transform=transformsv)
test_loader = DataLoader(test_ds, batch_size=1,
pin_memory=torch.cuda.is_available())
for test_data in test_loader:
test_images, test_labels = test_data["img"], test_data["label"]
with st.spinner('Performing Inference...'):
model = EfficientNetBN(
"efficientnet-b0", spatial_dims=3, in_channels=1, num_classes=3)
model.load_state_dict(torch.load(
'MCEBNfold1.pth', map_location='cpu'))
model.eval()
prediction = model(test_images.unsqueeze(1))
pred = prediction.argmax(dim=1).item()
class_names = ["SMCI", "AD", "CN"]
predicted_label = class_names[pred]
graph_input = list(chain.from_iterable(prediction.tolist()))
"Plot depicting Class Probabilities"
source = pd.DataFrame({
'Model output': graph_input,
'class': ["SMCI", "AD", "CN"]
})
bar_chart = alt.Chart(source).mark_bar().encode(
y='Model output:Q',
x='class:O',
)
element5 = st.altair_chart(bar_chart, use_container_width=True)
element6 = st.write(
f"The MRI Scan belong to the class **{predicted_label}**")
if pred == 0:
with st.spinner('Please wait...verifying the model output with another model'):
model_verify = monai.networks.nets.DenseNet264(spatial_dims=3, in_channels=1, out_channels=2)
model_verify.load_state_dict(torch.load(
'F3DENSENET264ADvsCNbest_metric_model_classification3d_dict.pth', map_location='cpu'))
model_verify.eval()
prediction_verify = model_verify(test_images.unsqueeze(1))
pred_verify = prediction_verify.argmax(dim=1).item()
class_names_verify = ["CN", "AD"]
predicted_label_verify = class_names_verify[pred_verify]
if pred_verify == 0:
if predicted_label_verify == predicted_label:
st.write(
f"Succesfully Verified the result, both models classified the scan as **{predicted_label_verify}**")
else:
st.write(
f"Verifying gave a different result ! **First model predicted as {predicted_label}, other predicted {predicted_label_verify}**")
if pred_verify == 1 :
model_verify = EfficientNetBN(
"efficientnet-b0", spatial_dims=3, in_channels=1, num_classes=2)
model_verify.load_state_dict(torch.load(
'EBNfold3.pth', map_location='cpu'))
model_verify.eval()
prediction_verify = model_verify(test_images.unsqueeze(1))
pred_verify = prediction_verify.argmax(dim=1).item()
class_names_verify = ["SMCI", "AD"]
predicted_label_verify = class_names_verify[pred_verify]
if predicted_label_verify == predicted_label:
st.write(
f"Succesfully Verified the result, both models classified the scan as **{predicted_label_verify}**")
else:
st.write(
f"Verifying gave a different result ! **First model predicted as {predicted_label}, other predicted {predicted_label_verify}**")
st.write("Kindly consider output of the second model to be more accurate")
if pred == 1:
with st.spinner('Please wait...verifying the model output with another model'):
model_verify = EfficientNetBN(
"efficientnet-b0", spatial_dims=3, in_channels=1, num_classes=2)
model_verify.load_state_dict(torch.load(
'EBNfold3.pth', map_location='cpu'))
model_verify.eval()
prediction_verify = model_verify(test_images.unsqueeze(1))
pred_verify = prediction_verify.argmax(dim=1).item()
class_names_verify = ["SMCI", "AD"]
predicted_label_verify = class_names_verify[pred_verify]
if predicted_label_verify == predicted_label:
st.write(
f"Succesfully Verified the result, both models classified the scan as **{predicted_label_verify}**")
else:
st.write(
f"Verifying gave a different result ! **First model predicted as {predicted_label}, other predicted {predicted_label_verify}**")
st.write("Kindly consider output of the second model to be more accurate")
if pred == 2:
with st.spinner('Please wait...verifying the model output with another model'):
model_verify = EfficientNetBN(
"efficientnet-b0", spatial_dims=3, in_channels=1, num_classes=2)
model_verify.load_state_dict(torch.load(
'ENB0ADvsCNbest_metric_model_classification3d_dict.pth', map_location='cpu'))
model_verify.eval()
prediction_verify = model_verify(test_images.unsqueeze(1))
pred_verify = prediction_verify.argmax(dim=1).item()
class_names_verify = ["CN", "AD"]
predicted_label_verify = class_names_verify[pred_verify]
if predicted_label_verify == predicted_label:
st.write(
f"Succesfully Verified the result, both models classified the scan as **{predicted_label_verify}**")
else:
st.write(
f"Verifying gave a different result ! **First model predicted as {predicted_label}, other predicted {predicted_label_verify}**")
st.write("Kindly consider output of the second model to be more accurate")
graph_input_1 = list(chain.from_iterable(prediction_verify.tolist()))
"Plot depicting verifying model outputs"
source_1 = pd.DataFrame({
'Model output': graph_input_1,
'class': class_names_verify
})
bar_chart_1 = alt.Chart(source_1).mark_bar().encode(
y='Model output:Q',
x='class:O',
)
st.altair_chart(bar_chart_1, use_container_width=True)
if len(file_upload) > 1:
print(len(file_upload))
if os.path.exists('tmp') == True:
shutil.rmtree('tmp')
os.makedirs('tmp')
for file in file_upload:
file.name = file.name
with open(file.name, "wb") as f:
f.write(file.getbuffer())
shutil.copy(file.name, 'tmp')
print(len(file_upload))
display_image = st.empty()
# display_image = ants.core.ants_image_io.dicom_read('tmp')
saved_path = 'uploaded_image'
display_image = dicom2nifti.convert_dicom.dicom_series_to_nifti('tmp', saved_path, reorient_nifti=False)
# nib.save(display_image, saved_path)
display_image = ants.image_read(f"{saved_path}.nii")
element2 = st.pyplot(ants.plot(display_image))
# b = display_image.to_nibabel()
# saved_path = 'uploaded_image'
# nib.save(b, saved_path)
processed_image = pre_process(f"{saved_path}.nii")
a = processed_image.to_nibabel()
saved_preprocessed_path = 'input_image'
nib.save(a, saved_preprocessed_path)
element3 = st.text("Preprocessed Image")
element4 = st.pyplot(ants.plot(f"{saved_preprocessed_path}.nii", cmap="seismic"))
transformsv = Compose(
[
LoadImaged(keys=["img"])
]
)
test_files = [{"img": f"{saved_preprocessed_path}.nii", "label": 1}]
test_ds = monai.data.Dataset(data=test_files, transform=transformsv)
test_loader = DataLoader(test_ds, batch_size=1,
pin_memory=torch.cuda.is_available())
for test_data in test_loader:
test_images, test_labels = test_data["img"], test_data["label"]
with st.spinner('Performing Inference...'):
model = EfficientNetBN(
"efficientnet-b0", spatial_dims=3, in_channels=1, num_classes=3)
model.load_state_dict(torch.load(
'MCEBNfold1.pth', map_location='cpu'))
model.eval()
prediction = model(test_images.unsqueeze(1))
pred = prediction.argmax(dim=1).item()
class_names = ["SMCI", "AD", "CN"]
predicted_label = class_names[pred]
graph_input = list(chain.from_iterable(prediction.tolist()))
"Plot depicting Class Probabilities"
source = pd.DataFrame({
'Model output': graph_input,
'class': ["SMCI", "AD", "CN"]
})
bar_chart = alt.Chart(source).mark_bar().encode(
y='Model output:Q',
x='class:O',
)
element5 = st.altair_chart(bar_chart, use_container_width=True)
element6 = st.write(
f"The MRI Scan belong to the class **{predicted_label}**")
if pred == 0:
with st.spinner('Please wait...verifying the model output with another model'):
model_verify = monai.networks.nets.DenseNet264(spatial_dims=3, in_channels=1, out_channels=2)
model_verify.load_state_dict(torch.load(
'F3DENSENET264ADvsCNbest_metric_model_classification3d_dict.pth', map_location='cpu'))
model_verify.eval()
prediction_verify = model_verify(test_images.unsqueeze(1))
pred_verify = prediction_verify.argmax(dim=1).item()
class_names_verify = ["CN", "AD"]
predicted_label_verify = class_names_verify[pred_verify]
if pred_verify == 0:
if predicted_label_verify == predicted_label:
st.write(
f"Succesfully Verified the result, both models classified the scan as **{predicted_label_verify}**")
else:
st.write(
f"Verifying gave a different result ! **First model predicted as {predicted_label}, other predicted {predicted_label_verify}**")
if pred_verify == 1 :
model_verify = EfficientNetBN(
"efficientnet-b0", spatial_dims=3, in_channels=1, num_classes=2)
model_verify.load_state_dict(torch.load(
'EBNfold3.pth', map_location='cpu'))
model_verify.eval()
prediction_verify = model_verify(test_images.unsqueeze(1))
pred_verify = prediction_verify.argmax(dim=1).item()
class_names_verify = ["SMCI", "AD"]
predicted_label_verify = class_names_verify[pred_verify]
if predicted_label_verify == predicted_label:
st.write(
f"Succesfully Verified the result, both models classified the scan as **{predicted_label_verify}**")
else:
st.write(
f"Verifying gave a different result ! **First model predicted as {predicted_label}, other predicted {predicted_label_verify}**")
st.write("Kindly consider output of the second model to be more accurate")
if pred == 1:
with st.spinner('Please wait...verifying the model output with another model'):
model_verify = EfficientNetBN(
"efficientnet-b0", spatial_dims=3, in_channels=1, num_classes=2)
model_verify.load_state_dict(torch.load(
'EBNfold3.pth', map_location='cpu'))
model_verify.eval()
prediction_verify = model_verify(test_images.unsqueeze(1))
pred_verify = prediction_verify.argmax(dim=1).item()
class_names_verify = ["SMCI", "AD"]
predicted_label_verify = class_names_verify[pred_verify]
if predicted_label_verify == predicted_label:
st.write(
f"Succesfully Verified the result, both models classified the scan as **{predicted_label_verify}**")
else:
st.write(
f"Verifying gave a different result ! **First model predicted as {predicted_label}, other predicted {predicted_label_verify}**")
st.write("Kindly consider output of the second model to be more accurate")
if pred == 2:
with st.spinner('Please wait...verifying the model output with another model'):
model_verify = monai.networks.nets.DenseNet264(spatial_dims=3, in_channels=1, out_channels=2)
model_verify.load_state_dict(torch.load(
'F3DENSENET264ADvsCNbest_metric_model_classification3d_dict.pth', map_location='cpu'))
model_verify.eval()
prediction_verify = model_verify(test_images.unsqueeze(1))
pred_verify = prediction_verify.argmax(dim=1).item()
class_names_verify = ["CN", "AD"]
predicted_label_verify = class_names_verify[pred_verify]
if predicted_label_verify == predicted_label:
st.write(
f"Succesfully Verified the result, both models classified the scan as **{predicted_label_verify}**")
else:
st.write(
f"Verifying gave a different result ! **First model predicted as {predicted_label}, other predicted {predicted_label_verify}**")
st.write("Kindly consider output of the second model to be more accurate")
graph_input_1 = list(chain.from_iterable(prediction_verify.tolist()))
"Plot depicting verifying model outputs"
source_1 = pd.DataFrame({
'Model output': graph_input_1,
'class': class_names_verify
})
bar_chart_1 = alt.Chart(source_1).mark_bar().encode(
y='Model output:Q',
x='class:O',
)
st.altair_chart(bar_chart_1, use_container_width=True)
st.markdown('''
''', unsafe_allow_html=True)
st.markdown('''#### Publications :book:''', unsafe_allow_html=True)
st.markdown("""1. [Transfer Learning for Alzheimer’s Disease through Neuroimaging Biomarkers: A Systematic Review](https://www.mdpi.com/1424-8220/21/21/7259 ) \n
Q1 Sensors
2. [End-to-End Deep Learning Architectures Using 3D Neuroimaging Biomarkers for Early Alzheimer’s Diagnosis](https://www.mdpi.com/2227-7390/10/15/2575) \n
Q2 mathematics
""", unsafe_allow_html=True)
st.markdown('''#### Contact details :mailbox:''', unsafe_allow_html=True)
st.markdown('''
Group :busts_in_silhouette: : http://www.sigte.tel.uva.es/index.php/en/homepage/
The eHealth and Telemedicine Group (GTe) of the University of Valladolid is a multidisciplinary international group consisting of telecommunications, informatics and medical doctors from different specialties. \n
Email :e-mail: : deevynkar@gmail.com''', unsafe_allow_html=True)