|
|
import sqlite3 |
|
|
import numpy as np |
|
|
import pandas as pd |
|
|
import gradio as gr |
|
|
from pickle import load |
|
|
from datetime import datetime |
|
|
import sqlalchemy |
|
|
from radiomics import featureextractor |
|
|
from sqlalchemy.orm import sessionmaker |
|
|
import nibabel as nib |
|
|
from PIL import Image |
|
|
|
|
|
extractor3D = featureextractor.RadiomicsFeatureExtractor("3DParams.yaml") |
|
|
with open("model.pickle", "rb") as file: |
|
|
loaded_model = load(file) |
|
|
|
|
|
def validation(username : str, password : str): |
|
|
if username == "" or password == "": |
|
|
return False |
|
|
table = pd.read_sql_table(table_name="Usuarios", con="sqlite:///database_test.db") |
|
|
row = table[table["Usuario"] == username] |
|
|
if row.empty: |
|
|
return False |
|
|
password_db = row["Contraseña"].to_numpy().tolist()[0] |
|
|
return password == password_db |
|
|
|
|
|
with gr.Blocks(title="Historial de diagnósticos") as ViewingHistory: |
|
|
history_dataframe = gr.Dataframe(visible=False, type="pandas", wrap=True, interactive=False) |
|
|
|
|
|
def update_dataframe(history_dataframe): |
|
|
temp = pd.read_sql_table(table_name="Predicciones", con="sqlite:///database_test.db") |
|
|
return gr.Dataframe(value=temp, visible=True, type="pandas", wrap=True, interactive=False) |
|
|
|
|
|
ViewingHistory.load(fn=update_dataframe, inputs=[history_dataframe], outputs=[history_dataframe]) |
|
|
|
|
|
with gr.Blocks(title="Clasificación") as AIModel: |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
image_file = gr.File(file_count="single", file_types=[".nii.gz", ".nii"], type="filepath", label="Imagen") |
|
|
segment_file = gr.File(file_count="single", file_types=[".nii.gz", ".nii"], type="filepath", label="Segmento") |
|
|
dropdown_navigator = gr.Dropdown(value="eje X", choices=["eje X", "eje Y", "eje Z"], filterable=True, type="value", label="Eje") |
|
|
|
|
|
slider = gr.Slider(visible=False) |
|
|
image_preview = gr.Image(visible=False) |
|
|
|
|
|
def preview_image(axis, image): |
|
|
brain_volume_data = nib.load(image).get_fdata() |
|
|
if axis == "eje X": |
|
|
middle_index = brain_volume_data.shape[0] // 2 |
|
|
max_index = brain_volume_data.shape[0] - 1 |
|
|
slice = brain_volume_data[middle_index, :, :] |
|
|
image = Image.fromarray(slice) |
|
|
image = image.rotate(90) |
|
|
elif axis == "eje Y": |
|
|
middle_index = brain_volume_data.shape[1] // 2 |
|
|
max_index = brain_volume_data.shape[1] - 1 |
|
|
slice = brain_volume_data[:, middle_index, :] |
|
|
image = Image.fromarray(slice) |
|
|
image = image.rotate(90) |
|
|
else: |
|
|
middle_index = brain_volume_data.shape[2] // 2 |
|
|
max_index = brain_volume_data.shape[2] - 1 |
|
|
slice = brain_volume_data[:, :, middle_index] |
|
|
image = Image.fromarray(slice) |
|
|
image = image.rotate(90) |
|
|
|
|
|
return ( |
|
|
gr.Slider(value=middle_index, minimum=0, maximum=max_index, visible=True), |
|
|
gr.Image(value=image, label="Previsualización", type="pil", visible=True, interactive=False, show_download_button=True) |
|
|
) |
|
|
|
|
|
def slicing_image(axis, image, index): |
|
|
brain_volume_data = nib.load(image).get_fdata() |
|
|
|
|
|
if axis == "eje X": |
|
|
slice = brain_volume_data[index, :, :] |
|
|
image = Image.fromarray(slice) |
|
|
image = image.rotate(90) |
|
|
elif axis == "eje Y": |
|
|
slice = brain_volume_data[:, index, :] |
|
|
image = Image.fromarray(slice) |
|
|
image = image.rotate(90) |
|
|
else: |
|
|
slice = brain_volume_data[:, :, index] |
|
|
image = Image.fromarray(slice) |
|
|
|
|
|
return ( |
|
|
gr.Image(value=image, label="Previsualización", type="pil", visible=True, interactive=False, show_download_button=True) |
|
|
) |
|
|
dropdown_navigator.change(fn=preview_image, inputs=[dropdown_navigator, image_file], outputs=[slider, image_preview]) |
|
|
image_file.upload(fn=preview_image, inputs=[dropdown_navigator, image_file], outputs=[slider, image_preview]) |
|
|
slider.change(fn=slicing_image, inputs=[dropdown_navigator, image_file, slider], outputs=[image_preview]) |
|
|
with gr.Column(): |
|
|
label_output = gr.Label(label="Resultado") |
|
|
comment_output = gr.Textbox(label="Observación", type="text", interactive=True) |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
clear_button = gr.ClearButton(value="Borrar", components=[image_file, segment_file, label_output, comment_output, dropdown_navigator]) |
|
|
with gr.Column(): |
|
|
submit_button = gr.Button(value="Enviar", variant="primary") |
|
|
|
|
|
def clear_image_preview(image_preview, slider): |
|
|
return (gr.Image(visible=False), gr.Slider(visible=False)) |
|
|
|
|
|
clear_button.click(fn=clear_image_preview, inputs=[image_preview, slider], outputs=[image_preview, slider]) |
|
|
with gr.Column(): |
|
|
flag_button = gr.Button(value="Guardar") |
|
|
|
|
|
def save_prediction(image, label_output, comment_output): |
|
|
grade1 = list(label_output.values())[0] |
|
|
grade2 = list(label_output.values())[1] |
|
|
engine = sqlalchemy.create_engine("sqlite:///database_test.db", echo=False) |
|
|
Session = sessionmaker(bind=engine) |
|
|
session = Session() |
|
|
metadata = sqlalchemy.MetaData() |
|
|
predictions_table = sqlalchemy.Table("Predicciones", metadata, autoload_with=engine) |
|
|
|
|
|
new_prediction = { |
|
|
"Imagen": image, |
|
|
"Grado 1":grade1, |
|
|
"Grado 2": grade2, |
|
|
"Observacion": comment_output, |
|
|
"Usuario ID": 1, |
|
|
"Ultima actualizacion": datetime.utcnow(), |
|
|
"Creado el": datetime.utcnow() |
|
|
} |
|
|
|
|
|
stmt = predictions_table.insert().values(**new_prediction) |
|
|
session.execute(stmt) |
|
|
session.commit() |
|
|
return gr.Info("Se ha guardado exitosamente") |
|
|
|
|
|
def classify_image(image, segment): |
|
|
features3D = extractor3D.execute(imageFilepath=image, maskFilepath=segment) |
|
|
dict = {} |
|
|
for key, value in zip(features3D.keys(), features3D.values()): |
|
|
if isinstance(value, np.ndarray): |
|
|
dict[key] = [value.tolist()] |
|
|
else: |
|
|
dict[key] = [value] |
|
|
temp = pd.DataFrame(dict).select_dtypes(exclude=["object"]).to_numpy() |
|
|
prediction = loaded_model.predict_proba(temp).tolist()[0] |
|
|
return {"Grado 1": prediction[0], "Grado 2": prediction[1]} |
|
|
|
|
|
flag_button.click(fn=save_prediction, inputs=[image_file, label_output, comment_output]).success(update_dataframe, history_dataframe, history_dataframe) |
|
|
submit_button.click(fn=classify_image, inputs=[image_file, segment_file], outputs=[label_output]) |
|
|
|
|
|
with gr.Blocks(title="Base de datos") as Database: |
|
|
with gr.Row(): |
|
|
table_dropdown = gr.Dropdown(value="Usuarios", choices=["Usuarios", "Predicciones"], |
|
|
filterable=True, label="Tabla") |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
action_dropdown = gr.Dropdown(choices=["Eliminar", "Descargar"], filterable=True, label="Acciones") |
|
|
with gr.Column(): |
|
|
id_dropdown = gr.Dropdown(visible=False, filterable=True, label="Identificador (ID)") |
|
|
with gr.Column(): |
|
|
action_button = gr.Button(visible=False) |
|
|
with gr.Row(): |
|
|
database_dataframe = gr.Dataframe(visible=False, type="pandas", wrap=True, interactive=False) |
|
|
|
|
|
def on_table_dropdown_change(table_dropdown, database_dataframe, id_dropdown): |
|
|
temp = pd.read_sql_table(table_dropdown, "sqlite:///database_test.db") |
|
|
ids = temp["ID"].values.flatten().tolist() |
|
|
return ( |
|
|
gr.Dataframe(value=temp, visible=True, type="pandas", wrap=True, interactive=False), |
|
|
gr.Dropdown(choices=ids, visible=True, filterable=True, label="Identificador (ID)"), |
|
|
) |
|
|
|
|
|
def on_database_load(table_dropdown, database_dataframe): |
|
|
temp = pd.read_sql_table(table_dropdown, "sqlite:///database_test.db") |
|
|
return gr.Dataframe(value=temp, visible=True, type="pandas", wrap=True, interactive=False) |
|
|
|
|
|
def on_action_dropdown_change(action_dropdown): |
|
|
return gr.Button(value=action_dropdown, visible=True, variant="primary") |
|
|
|
|
|
def on_action_button_click(table_dropdown, action_dropdown, id_dropdown, database_dataframe): |
|
|
if action_dropdown == "Eliminar": |
|
|
engine = sqlalchemy.create_engine("sqlite:///database_test.db", echo=False) |
|
|
Session = sessionmaker(bind=engine) |
|
|
session = Session() |
|
|
metadata = sqlalchemy.MetaData() |
|
|
table = sqlalchemy.Table(table_dropdown, metadata, autoload_with=engine) |
|
|
stmt = sqlalchemy.delete(table).where(table.c.ID == id_dropdown) |
|
|
session.execute(stmt) |
|
|
session.commit() |
|
|
return gr.Info(f"Se ha eliminado el registro #{id_dropdown}") |
|
|
elif action_dropdown == "Descargar": |
|
|
if table_dropdown == "Predicciones": |
|
|
file_path = database_dataframe["Imagen"].to_numpy().tolist()[0] |
|
|
print(file_path) |
|
|
return gr.DownloadButton(value=file_path) |
|
|
|
|
|
|
|
|
table_dropdown.change(fn=on_table_dropdown_change, inputs=[table_dropdown, database_dataframe, id_dropdown], outputs=[database_dataframe, id_dropdown]) |
|
|
Database.load(fn=on_database_load, inputs=[table_dropdown, database_dataframe], outputs=[database_dataframe]).success(fn=on_table_dropdown_change, inputs=[table_dropdown, database_dataframe, id_dropdown], outputs=[database_dataframe, id_dropdown]) |
|
|
action_dropdown.change(fn=on_action_dropdown_change, inputs=[action_dropdown], outputs=[action_button]) |
|
|
action_button.click(fn=on_action_button_click, inputs=[table_dropdown, action_dropdown, id_dropdown, database_dataframe], outputs=[action_dropdown]) |
|
|
|
|
|
|
|
|
with gr.Blocks(title="Información de usuario") as AdminInformation: |
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
input_profile_image = gr.Image(interactive=False) |
|
|
with gr.Column(): |
|
|
input_first_names = gr.Textbox(label="Nombres", interactive=False, type="text", max_lines=1) |
|
|
input_username = gr.Textbox(label="Usuario", interactive=False, type="text", max_lines=1) |
|
|
input_is_admin = gr.Textbox(label="Rol", interactive=False, type="text", max_lines=1) |
|
|
with gr.Column(): |
|
|
input_last_names = gr.Textbox(label="Apellidos", interactive=False, type="text", max_lines=1) |
|
|
input_email = gr.Textbox(label="Correo electrónico", interactive=False, type="email", max_lines=1) |
|
|
input_phone = gr.Textbox(label="Número de teléfono", interactive=False, type="text", max_lines=1) |
|
|
with gr.Row(): |
|
|
with gr.Row(): |
|
|
edit_button = gr.Button(value="Editar") |
|
|
save_button = gr.Button(value="Guardar", variant="primary") |
|
|
|
|
|
def FillFields(input_username, input_first_names, input_last_names, input_email, input_phone, input_is_admin): |
|
|
|
|
|
table = pd.read_sql_table(table_name="Usuarios", con="sqlite:///database_test.db") |
|
|
row = table[table["ID"] == 1] |
|
|
|
|
|
if not row.empty: |
|
|
username_db = row["Usuario"].to_numpy().tolist()[0] |
|
|
first_names_db = row["Nombres"].to_numpy().tolist()[0] |
|
|
last_names_db = row["Apellidos"].to_numpy().tolist()[0] |
|
|
email_db = row["Correo electronico"].to_numpy().tolist()[0] |
|
|
phone_db = row["Telefono"].to_numpy().tolist()[0] |
|
|
is_admin_db = row["Es Administrador"].to_numpy().tolist()[0] |
|
|
else: |
|
|
username_db = "" |
|
|
first_names_db = "" |
|
|
last_names_db = "" |
|
|
email_db = "" |
|
|
phone_db = "" |
|
|
is_admin_db = False |
|
|
|
|
|
return ( |
|
|
gr.Textbox(value=username_db, label="Usuario", interactive=False, max_lines=1), |
|
|
gr.Textbox(value=first_names_db, label="Nombres", interactive=False, max_lines=1), |
|
|
gr.Textbox(value=last_names_db, label="Apellidos", interactive=False, max_lines=1), |
|
|
gr.Textbox(value=email_db, label="Correo electrónico", interactive=False, max_lines=1), |
|
|
gr.Textbox(value=phone_db, label="Número de teléfono", interactive=False, max_lines=1), |
|
|
gr.Textbox(value="Administrador" if is_admin_db else "Doctor", label="Rol", interactive=False, type="text", max_lines=1) |
|
|
) |
|
|
|
|
|
def make_editable(edit_button, input_username, input_first_names, input_last_names, input_email, input_phone): |
|
|
|
|
|
if edit_button == "Editar": |
|
|
return ( |
|
|
gr.Button(value="Cancelar"), |
|
|
gr.Textbox(value=input_username, interactive=True), |
|
|
gr.Textbox(value=input_first_names, interactive=True), |
|
|
gr.Textbox(value=input_last_names, interactive=True), |
|
|
gr.Textbox(value=input_email, interactive=True), |
|
|
gr.Textbox(value=input_phone, interactive=True), |
|
|
) |
|
|
else: |
|
|
return ( |
|
|
gr.Button(value="Editar"), |
|
|
gr.Textbox(value=input_username, interactive=True), |
|
|
gr.Textbox(value=input_first_names, interactive=True), |
|
|
gr.Textbox(value=input_last_names, interactive=True), |
|
|
gr.Textbox(value=input_email, interactive=True), |
|
|
gr.Textbox(value=input_phone, interactive=True), |
|
|
) |
|
|
|
|
|
def save_values(input_username, input_first_names, input_last_names, input_email, input_phone): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
engine = sqlalchemy.create_engine("sqlite:///database_test.db", echo=False) |
|
|
Session = sessionmaker(bind=engine) |
|
|
session = Session() |
|
|
metadata = sqlalchemy.MetaData() |
|
|
table = sqlalchemy.Table("Usuarios", metadata, autoload_with=engine) |
|
|
new_user = { |
|
|
"Usuario": input_username, |
|
|
"Nombres": input_first_names, |
|
|
"Apellidos": input_last_names, |
|
|
"Correo electronico": input_email, |
|
|
"Telefono": input_phone |
|
|
} |
|
|
stmt = sqlalchemy.update(table).where(table.c.ID == 1).values(**new_user) |
|
|
session.execute(stmt) |
|
|
session.commit() |
|
|
return ( |
|
|
gr.Textbox(value=input_username, interactive=False), |
|
|
gr.Textbox(value=input_first_names, interactive=False), |
|
|
gr.Textbox(value=input_last_names, interactive=False), |
|
|
gr.Textbox(value=input_email, interactive=False), |
|
|
gr.Textbox(value=input_phone, interactive=False), |
|
|
) |
|
|
|
|
|
AdminInformation.load(fn=FillFields, inputs=[input_username, input_first_names, input_last_names, input_email, input_phone, input_is_admin], outputs=[input_username, input_first_names, input_last_names, input_email, input_phone, input_is_admin]) |
|
|
edit_button.click(fn=make_editable, inputs=[edit_button, input_username, input_first_names, input_last_names, input_email, input_phone], outputs=[edit_button, input_username, input_first_names, input_last_names, input_email, input_phone]) |
|
|
save_button.click(fn=save_values, inputs=[input_username, input_first_names, input_last_names, input_email, input_phone], outputs=[input_username, input_first_names, input_last_names, input_email, input_phone]) |
|
|
|
|
|
Demo = gr.TabbedInterface( |
|
|
interface_list=[AIModel, ViewingHistory, Database, AdminInformation], |
|
|
tab_names=["Aplicación", "Historial", "Base de datos", "Administrador"], |
|
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
Demo.launch( |
|
|
share=True, |
|
|
debug=True, |
|
|
inbrowser=True, |
|
|
auth=validation |
|
|
) |