Saltar a contenido

Proceso de Validación: Python vs MATLAB - EPPA

Fecha: 2024-12-24 Responsable: Luis Arancibia (con asistencia de Claude)


Resumen Ejecutivo

Se migró exitosamente el sistema de evaluación postural EPPA de MATLAB a Python/FastAPI, validando que los cálculos producen resultados equivalentes.


1. Contexto Inicial

Problema Original

  • El sistema EPPA estaba implementado en MATLAB (archivos .m)
  • Se detectaron "datos locos" en la base de datos de evaluaciones
  • La Dra. Cristina Oleari identificó valores anómalos (ej: lordosis de 51 cm en vez de 5 cm)

Archivos MATLAB Originales

matlab/
├── InterfazMedicionFrenteJulio2024v2.m
├── InterfazMedicionEspaldaJulio2024v2.m
├── InterfazMedicionPerfilDerechoJulio2024.m
└── InterfazMedicionPerfilIzquierdoJulio2024.m

2. Análisis de "Datos Locos"

2.1 Errores de Coma Decimal (x10)

Se encontraron 4 casos donde los valores estaban multiplicados por 10:

Evaluado Evaluador Variable Original Corregido
3 4 Tangentes Dorso-Sacro 45.73 cm 4.57 cm
3 4 Lordosis lumbar 51.35 cm 5.14 cm
6 8 Tangentes Dorso-Sacro 43.48 cm 4.35 cm
6 8 Lordosis lumbar 49.13 cm 4.91 cm

2.2 Causa Raíz Identificada

Analizando el código MATLAB, descubrimos que:

  1. La Lordosis Lumbar es CALCULADA automáticamente, no ingresada manualmente:

    % InterfazMedicionPerfilDerechoJulio2024.m, línea 672
    DistanciaApexSacro = handles.FC * (XAPEXLUMBAR - handles.Xsacro);
    

  2. El código espera el nombre exacto "Punto Sacro":

    switch handles.lista
        case 'Punto Sacro'
            handles.Xsacro = x1;  % Solo se asigna si el nombre es EXACTO
    

  3. Los evaluadores usaron nombres alternativos:

  4. Usaron: "Espina Ilíaca Posterosuperior"
  5. El código esperaba: "Punto Sacro"
  6. Resultado: Xsacro quedó en 0, inflando los valores

2.3 Inconsistencias de Signo

Se encontraron 19 casos de signos inconsistentes entre evaluadores. Causa: cuando el ángulo está cerca de 180°, diferencias de 1-2 píxeles en la posición del marcador cambian el signo del resultado.


3. Implementación Python

3.1 Módulo de Cálculos (calculations.py)

Traducimos todas las fórmulas de MATLAB a Python:

# Factor de Calibración
def calculate_fc(p1, p2, known_distance=10.0):
    d12 = math.sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)
    return known_distance / d12

# Ángulo entre vectores (producto punto)
def calculate_angle_between_vectors(a, b):
    dot_product = a[0]*b[0] + a[1]*b[1]
    norm_a = math.sqrt(a[0]**2 + a[1]**2)
    norm_b = math.sqrt(b[0]**2 + b[1]**2)
    cos_angle = dot_product / (norm_a * norm_b)
    return math.degrees(math.acos(cos_angle))

# Lordosis Lumbar
def calc_lordosis_lumbar(apex_lumbar, punto_sacro, fc, is_perfil_derecho=True):
    if is_perfil_derecho:
        dist = fc * (apex_lumbar[0] - punto_sacro[0])
    else:
        dist = fc * (punto_sacro[0] - apex_lumbar[0])
    # ... diagnóstico según rangos

3.2 API FastAPI (main.py)

Creamos endpoints que procesan archivos .mat y calculan métricas:

@app.post("/processMatFile")
async def process_mat_file(file: UploadFile, fc: float = Query(0.1)):
    """
    Sube un archivo .mat y calcula todas las métricas automáticamente.
    Detecta la vista y aplica los cálculos correspondientes.
    """

3.3 Vistas Implementadas

Vista Métricas Calculadas
Frente Inclinación cabeza, hombros, pelvis, Ángulo Q
Posterior Inclinación cabeza, Ángulo calcáneo
Perfil Derecho Ubicación sagital cabeza, Lordosis lumbar, Ángulo codo/rodilla
Perfil Izquierdo Igual que Perfil Derecho (con signos ajustados)

4. Validación

4.1 Script de Validación (validation/validate_calculations.py)

Procesa todos los archivos .mat de pacientes y muestra los cálculos:

python validation/validate_calculations.py

4.2 Tests Automatizados (tests/test_eppa_api.py)

9 tests que verifican: - API health check - Calibración de grid - Procesamiento de las 4 vistas - Rangos de valores razonables - Consistencia entre pacientes

pytest tests/test_eppa_api.py -v
# Resultado: 9/9 PASSED

4.3 Datos de Prueba

Pacientes correctos (sin errores): - Ana Lucia Zanellatto (post-tratamiento) - Delfina Nastrun - Gisella Brundo (pre-tratamiento) - Simona Diab

Pacientes con datos locos (errores corregidos): - Evaluado 3, Evaluador 4 - Evaluado 6, Evaluador 8


5. Archivos Generados

000079-eppa/
├── calculations.py          # Fórmulas MATLAB → Python
├── main.py                  # API FastAPI actualizada
├── docs/
│   ├── DATOS-LOCOS.md       # Análisis de errores
│   └── PROCESO-VALIDACION.md # Este documento
├── validation/
│   ├── fix_crazy_data.py    # Detector/corrector de errores
│   ├── validate_calculations.py # Validación Python vs MATLAB
│   ├── crazy_data_report.txt
│   └── crazy_data_analysis.json
├── tests/
│   └── test_eppa_api.py     # Tests automatizados
└── datos-labis/
    ├── Base completa- CORREGIDA.xlsx
    ├── Ejemplos datos locos/
    └── Ejemplos pacientes correctos/

6. Conclusiones

  1. Migración exitosa: Los cálculos de Python producen resultados equivalentes a MATLAB
  2. Causa raíz identificada: Los errores x10 fueron por nombres de marcadores no reconocidos
  3. Validación completa: 9/9 tests pasando con datos reales de pacientes
  4. Documentación: Todo el proceso está documentado para referencia futura

7. Recomendaciones para el Software MATLAB

% Agregar alias para nombres de marcadores
case {'Punto Sacro', 'Espina Ilíaca Posterosuperior', 'EIPS'}
    handles.Xsacro = x1;

8. Comandos Útiles

# Ejecutar API
uvicorn main:app --reload

# Ejecutar tests
pytest tests/test_eppa_api.py -v

# Validar cálculos
python validation/validate_calculations.py

# Detectar datos locos
python validation/fix_crazy_data.py

# Corregir datos locos
python validation/fix_crazy_data.py --fix

Última actualización: 2024-12-24