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:
-
La Lordosis Lumbar es CALCULADA automáticamente, no ingresada manualmente:
% InterfazMedicionPerfilDerechoJulio2024.m, línea 672 DistanciaApexSacro = handles.FC * (XAPEXLUMBAR - handles.Xsacro); -
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 -
Los evaluadores usaron nombres alternativos:
- Usaron: "Espina Ilíaca Posterosuperior"
- El código esperaba: "Punto Sacro"
- Resultado:
Xsacroquedó 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¶
- Migración exitosa: Los cálculos de Python producen resultados equivalentes a MATLAB
- Causa raíz identificada: Los errores x10 fueron por nombres de marcadores no reconocidos
- Validación completa: 9/9 tests pasando con datos reales de pacientes
- 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