Commit 1b487c30 by Jaime Collado

Updated PiRADS classifier and vectorizer

parent 4ac69518
import joblib
from datetime import timedelta
from typing import List
from fastapi import FastAPI, Depends, HTTPException, status, Body
from fastapi.security import OAuth2PasswordRequestForm
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
import schemas, security, dependencies, crud, database, utils
database.Base.metadata.create_all(bind=database.engine)
# APP
app = FastAPI()
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Load the vectorizer
with open("./vectorizers/pirads_tfidf.pkl", "rb") as pickled_file:
vectorizer = joblib.load(pickled_file)
# Load the model
with open("./classifiers/pirads_model.joblib", "rb") as pickled_file:
clf = joblib.load(pickled_file)
def _predict(text, model, vectorizer):
# Preprocess input text
clean_text = utils.preprocessing_text(text)
clean_text = utils.clear_birads(clean_text)
# Vectorize text
X_test = vectorizer.transform([clean_text])
# Predict outputs
probs = model.predict_proba(X_test)
probs = [prob[0][1] for prob in probs]
return probs
# Methods
@app.post("/register", response_model=schemas.User)
def register(user: schemas.UserCreate, db: Session = Depends(dependencies.get_db)):
db_user = crud.get_user(db, username=user.username)
if db_user:
raise HTTPException(status_code=400, detail="Username already registered")
return crud.create_user(db=db, user=user)
@app.post("/token", response_model=schemas.Token)
async def login_for_access_token(
form_data: OAuth2PasswordRequestForm = Depends(),
db: Session = Depends(dependencies.get_db)
):
user = crud.authenticate_user(db, form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=security.ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = security.create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}
@app.post("/predict", response_model=List[schemas.OutputData])
async def predict(
input_data: List[schemas.InputData] = Body(
example =
[
{
"id": 0,
"text":
"""INFORMACION CLINICA
elevación de PSA.
HALLAZGOS
Se sigue la clasificación PIRADS V2.1 de Marzo de 2019.
Volumen prostático prostático: 39 cc.
Hipertrofia de la zona de transición que comprime y adelgaza la zona periférica.
No se observan áreas claramente sospechosas de carcinoma clínicamente significativo en T2 ni secuencias de difusión.
Múltiples imágenes nodulares en zona transicional compatibles en primer término con nódulos hiperplásicos (PIRADS 2).
Vesículas seminales y ampollas deferenciales presentes y simétricas. Sin alteraciones parietales ni del contenido.
No se observan adenomegalias.
Estructuras óseas sin lesiones sospechosas de malignidad.
CONCLUSIÓN:
HPB.
No se observan áreas claramente sospechosas de carcinoma clínicamente significativo demostrables por esta técnica.
"""
},
{
"id": 1,
"text":
"""INFORMACION CLINICA
elevación persistente de PSA.
HALLAZGOS
Se sigue la clasificación PIRADS V2.1 de Marzo de 2019.
Volumen prostático prostático: 126 cc.
Hipertrofia de la zona de transición que comprime y adelgaza la zona periférica.
No se observan áreas claramente sospechosas de carcinoma clínicamente significativo en T2 ni secuencias de difusión.
Múltiples imágenes nodulares en zona transicional compatibles en primer término con nódulos hiperplásicos (PIRADS 1 y 2).
Vesículas seminales y ampollas deferenciales presentes y simétricas. Sin alteraciones parietales ni del contenido.
No se observan adenomegalias.
Estructuras óseas sin lesiones sospechosas de malignidad.
CONCLUSIÓN:
HPB.
No se observan áreas claramente sospechosas de carcinoma clínicamente significativo demostrables por esta técnica.
Se sugiere correlación estrecha con evolución de parámetros clínicos. Si en base a criterios clínicos fuera necesaria la biopsia, dada la ausencia de hallazgos en RM, debería realizarse de modo sistemático.
"""
}
]
),
current_user: str = Depends(dependencies.get_current_active_user)
):
# Input data: [{"id": 1, "text": "a"}, {"id": 2, "text": "b"}]
predictions = []
for report in input_data:
prediction = _predict(text=report.text, model=clf, vectorizer=vectorizer)
predictions.append(
{
"id": report.id,
"prediction": prediction
}
)
# Return predictions
return predictions
\ No newline at end of file
No preview for this file type
No preview for this file type
[
{
"id": 0,
"text": "EXPLORACIONES:\nMamografía tomosíntesis\nEcografía mamaria\n\n\nINFORMACION CLINICA\n\nRefiere dolor en CCEE de MI. Remitida para valoración. \n\nCOMPARADO CON:\n\nNo dispongo de estudios previos con los que comparar el actual. \n\nHALLAZGOS:\n\nSe realiza mamografía bilateral (proyecciones OML y CC) así como tomosíntesis en proyección CC y ecografía de ambas mamas. \n\nParénquima mamario muy denso, de distribución y características ecográficas normales (Patrón D ACR).\n\n\n.- En región paraareolar externa de MI se identifica un quiste de gran tamaño con una pequeña lesión focal dependiente de su pared, de 4 mm de diámetro, sugestivo de papiloma (BI-RADS 4a). \n\n\n2.- La zona dolorosa en CCEE de MI se corresponde con un quiste simple a tensión de 21 mm de diámetro (BI-RADS 2). \n\n\n3.- Calcificaciones benignas dispersas en ambas mamas (BI-RADS 2). Innumerables quistes simples de diferente tamaño dispersos en ambas mamas, algunos de gran tamaño y otros con contenido débilmente ecogénico en su interior (BI\n-RADS 2). No se observan otras alteraciones significativas en el momento actual.\n\nCONCLUSION:\n\nBI-RADS 4a. Se recomienda realizar PAAF/BAG de la posible lesión papilomatosa localizada en MI. También se recomienda dejar un marcador metálico en el lugar de la punción por la posibilidad de que al puncionar el quiste la lesión pase desapercibida en futuros estudios. Por otra parte, se recomienda realizar PAAF, con guía ecográfica e intención evacuadora, del quiste sintomático localizado en MI."
},
{
"id": 1,
"text": "EXPLORACIONES:\nMamografía tomosíntesis\nEcografía mamaria\n\n\nINFORMACION CLINICA\n\nRefiere dolor en CCEE de MI. Remitida para valoración. \n\nCOMPARADO CON:\n\nNo dispongo de estudios previos con los que comparar el actual. \n\nHALLAZGOS:\n\nSe realiza mamografía bilateral (proyecciones OML y CC) así como tomosíntesis en proyección CC y ecografía de ambas mamas. \n\nParénquima mamario muy denso, de distribución y características ecográficas normales (Patrón D ACR).\n\n\n.- En región paraareolar externa de MI se identifica un quiste de gran tamaño con una pequeña lesión focal dependiente de su pared, de 4 mm de diámetro, sugestivo de papiloma (BI-RADS 4a). \n\n\n2.- La zona dolorosa en CCEE de MI se corresponde con un quiste simple a tensión de 21 mm de diámetro (BI-RADS 2). \n\n\n3.- Calcificaciones benignas dispersas en ambas mamas (BI-RADS 2). Innumerables quistes simples de diferente tamaño dispersos en ambas mamas, algunos de gran tamaño y otros con contenido débilmente ecogénico en su interior (BI\n-RADS 2). No se observan otras alteraciones significativas en el momento actual.\n\nCONCLUSION:\n\nBI-RADS 4a. Se recomienda realizar PAAF/BAG de la posible lesión papilomatosa localizada en MI. También se recomienda dejar un marcador metálico en el lugar de la punción por la posibilidad de que al puncionar el quiste la lesión pase desapercibida en futuros estudios. Por otra parte, se recomienda realizar PAAF, con guía ecográfica e intención evacuadora, del quiste sintomático localizado en MI."
}
]
import joblib import uvicorn
from app import app
from datetime import timedelta if __name__ == '__main__':
from typing import List uvicorn.run(app, host='0.0.0.0', port=1448, log_level='info')
\ No newline at end of file
from fastapi import FastAPI, Depends, HTTPException, status, Body
from fastapi.security import OAuth2PasswordRequestForm
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
import schemas, security, dependencies, crud, database, utils
database.Base.metadata.create_all(bind=database.engine)
# APP
app = FastAPI()
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Load the vectorizer
with open("./vectorizers/birads_tfidf.pkl", "rb") as pickled_file:
vectorizer = joblib.load(pickled_file)
# Load the model
with open("./classifiers/birads_model.joblib", "rb") as pickled_file:
clf = joblib.load(pickled_file)
def _predict(text, model, vectorizer):
# Preprocess input text
clean_text = utils.preprocessing_text(text)
clean_text = utils.clear_birads(clean_text)
# Vectorize text
X_test = vectorizer.transform([clean_text])
# Predict outputs
probs = model.predict_proba(X_test)
probs = [prob[0][1] for prob in probs]
return probs
# Methods
@app.post("/register", response_model=schemas.User)
def register(user: schemas.UserCreate, db: Session = Depends(dependencies.get_db)):
db_user = crud.get_user(db, username=user.username)
if db_user:
raise HTTPException(status_code=400, detail="Email already registered")
return crud.create_user(db=db, user=user)
@app.post("/token", response_model=schemas.Token)
async def login_for_access_token(
form_data: OAuth2PasswordRequestForm = Depends(),
db: Session = Depends(dependencies.get_db)
):
user = crud.authenticate_user(db, form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=security.ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = security.create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}
@app.post("/predict", response_model=List[schemas.OutputData])
async def predict(
input_data: List[schemas.InputData] = Body(
example =
[
{
"id": 0,
"text": "EXPLORACIONES:\nMamografía tomosíntesis\nEcografía mamaria\n\n\nINFORMACION CLINICA\n\nRefiere dolor en CCEE de MI. Remitida para valoración. \n\nCOMPARADO CON:\n\nNo dispongo de estudios previos con los que comparar el actual. \n\nHALLAZGOS:\n\nSe realiza mamografía bilateral (proyecciones OML y CC) así como tomosíntesis en proyección CC y ecografía de ambas mamas. \n\nParénquima mamario muy denso, de distribución y características ecográficas normales (Patrón D ACR).\n\n\n.- En región paraareolar externa de MI se identifica un quiste de gran tamaño con una pequeña lesión focal dependiente de su pared, de 4 mm de diámetro, sugestivo de papiloma (BI-RADS 4a). \n\n\n2.- La zona dolorosa en CCEE de MI se corresponde con un quiste simple a tensión de 21 mm de diámetro (BI-RADS 2). \n\n\n3.- Calcificaciones benignas dispersas en ambas mamas (BI-RADS 2). Innumerables quistes simples de diferente tamaño dispersos en ambas mamas, algunos de gran tamaño y otros con contenido débilmente ecogénico en su interior (BI\n-RADS 2). No se observan otras alteraciones significativas en el momento actual.\n\nCONCLUSION:\n\nBI-RADS 4a. Se recomienda realizar PAAF/BAG de la posible lesión papilomatosa localizada en MI. También se recomienda dejar un marcador metálico en el lugar de la punción por la posibilidad de que al puncionar el quiste la lesión pase desapercibida en futuros estudios. Por otra parte, se recomienda realizar PAAF, con guía ecográfica e intención evacuadora, del quiste sintomático localizado en MI."
},
{
"id": 1,
"text": "EXPLORACIONES:\nMamografía tomosíntesis\nEcografía mamaria\n\n\nINFORMACION CLINICA\n\nRefiere dolor en CCEE de MI. Remitida para valoración. \n\nCOMPARADO CON:\n\nNo dispongo de estudios previos con los que comparar el actual. \n\nHALLAZGOS:\n\nSe realiza mamografía bilateral (proyecciones OML y CC) así como tomosíntesis en proyección CC y ecografía de ambas mamas. \n\nParénquima mamario muy denso, de distribución y características ecográficas normales (Patrón D ACR).\n\n\n.- En región paraareolar externa de MI se identifica un quiste de gran tamaño con una pequeña lesión focal dependiente de su pared, de 4 mm de diámetro, sugestivo de papiloma (BI-RADS 4a). \n\n\n2.- La zona dolorosa en CCEE de MI se corresponde con un quiste simple a tensión de 21 mm de diámetro (BI-RADS 2). \n\n\n3.- Calcificaciones benignas dispersas en ambas mamas (BI-RADS 2). Innumerables quistes simples de diferente tamaño dispersos en ambas mamas, algunos de gran tamaño y otros con contenido débilmente ecogénico en su interior (BI\n-RADS 2). No se observan otras alteraciones significativas en el momento actual.\n\nCONCLUSION:\n\nBI-RADS 4a. Se recomienda realizar PAAF/BAG de la posible lesión papilomatosa localizada en MI. También se recomienda dejar un marcador metálico en el lugar de la punción por la posibilidad de que al puncionar el quiste la lesión pase desapercibida en futuros estudios. Por otra parte, se recomienda realizar PAAF, con guía ecográfica e intención evacuadora, del quiste sintomático localizado en MI."
}
]
),
current_user: str = Depends(dependencies.get_current_active_user)
):
# Input data: [{"id": 1, "text": "a"}, {"id": 2, "text": "b"}]
predictions = []
for report in input_data:
prediction = _predict(text=report.text, model=clf, vectorizer=vectorizer)
predictions.append(
{
"id": report.id,
"prediction": prediction
}
)
# Return predictions
return predictions
\ No newline at end of file
No preview for this file type
No preview for this file type
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment