Marcadores Mínimos por Variable - EPPA¶
Versión: 1.0 Fecha: 2025-12-30 Propósito: Referencia rápida de qué marcadores son necesarios para calcular cada variable
🎯 Objetivo de Este Documento¶
Este documento responde a la pregunta: "¿Qué marcadores mínimos necesito para calcular la variable X?"
Casos de uso: - ✅ Evaluación parcial (ej: solo rodillas, solo hombros) - ✅ Exoesqueletos (no se pueden marcar todos los puntos) - ✅ Pacientes con ropa/vendajes que cubren zonas - ✅ Investigación enfocada en una región específica
⚠️ IMPORTANTE: Si falta un marcador requerido, la variable aparecerá como "Punto no visible" y NO se calculará.
📐 Marcadores Universales (Todas las Vistas)¶
Estos marcadores son OBLIGATORIOS para todas las vistas:
| Marcador | Propósito | Notas |
|---|---|---|
| Punto de Calibración 1 | Calcular Factor de Calibración (FC) | Separados exactamente 10 cm |
| Punto de Calibración 2 | Calcular Factor de Calibración (FC) | Separados exactamente 10 cm |
| Línea Vertical de Referencia (LVR) | Referencia para distancias horizontales | Coordenada X en píxeles |
Cálculo del FC:
D12 = distancia_euclidiana(punto_cal_1, punto_cal_2) # en píxeles
FC = 10.0 / D12 # cm por píxel
⚠️ SIN ESTOS 3, NINGUNA VARIABLE SE PUEDE CALCULAR
👁️ VISTA ANTERIOR (Frente)¶
Región: Cérvico-Cefálica¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula |
|---|---|---|---|---|
| 1 | Ángulo de Inclinación Cabeza | • Tragus Izquierdo • Tragus Derecho |
- | angle(tragus_izq, tragus_der) |
| 2 | Rotación Eminencia Frontal Media | • Eminencia Frontal Media • LVR • FC |
- | FC × (X_efm - LVR) |
| 3 | Rotación Espina Nasal | • Espina Nasal • LVR • FC |
- | FC × (X_espina - LVR) |
| 4 | Rotación Punto Mentoniano | • Punto Mentoniano • LVR • FC |
- | FC × (X_menton - LVR) |
Región: Tronco - Columna¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula |
|---|---|---|---|---|
| 5 | Rotación Escotadura Esternal | • Escotadura Esternal • LVR • FC |
- | FC × (X_escot - LVR) |
| 6 | Rotación Apéndice Xifoides | • Apéndice Xifoides • LVR • FC |
- | FC × (X_xifoid - LVR) |
| 7 | Rotación Sínfisis Pubiana | • Sínfisis Pubiana • LVR • FC |
- | FC × (X_sinfis - LVR) |
| 8 | Ángulo de Inclinación Tronco | • Sínfisis Pubiana • Escotadura Esternal |
- | angle_vertical(sinfisis, escotadura) |
Región: Cintura Escapular - Miembro Superior¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula |
|---|---|---|---|---|
| 9 | Ángulo de Inclinación Hombros | • Acromion Izquierdo • Acromion Derecho |
- | angle(acromion_izq, acromion_der) |
Región: Cintura Pélvica - Miembro Inferior¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula |
|---|---|---|---|---|
| 10 | Ángulo de Inclinación Pelvis | • EIAS Izquierda • EIAS Derecha |
- | angle(eias_izq, eias_der) |
| 11 | Ángulo Q Derecho | • EIAS Derecha • Centro Rótula Derecha • TAT Derecha |
- | angle_q(tat, rotula, eias) |
| 12 | Ángulo Q Izquierdo | • EIAS Izquierda • Centro Rótula Izquierda • TAT Izquierda |
- | angle_q(tat, rotula, eias) |
Total marcadores Vista Anterior: 17 marcadores + 2 calibración + LVR = 20 puntos
👁️ VISTA POSTERIOR (Espalda)¶
Región: Cérvico-Cefálica¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula |
|---|---|---|---|---|
| 1 | Ángulo de Inclinación Cabeza | • Lóbulo Oreja Izquierda • Lóbulo Oreja Derecha |
- | angle(lobulo_izq, lobulo_der) |
Región: Tronco - Columna¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula |
|---|---|---|---|---|
| 2 | Desbalance Coronal C7 | • C7 • LVR • FC |
- | FC × (X_c7 - LVR) |
| 3 | Desbalance Coronal T3 | • T3 • LVR • FC |
- | FC × (X_t3 - LVR) |
| 4 | Desbalance Coronal T7 | • T7 • LVR • FC |
- | FC × (X_t7 - LVR) |
| 5 | Desbalance Coronal T12 | • T12 • LVR • FC |
- | FC × (X_t12 - LVR) |
| 6 | Desbalance Coronal L5 | • L5 • LVR • FC |
- | FC × (X_l5 - LVR) |
| 7 | Punto Interno Espina Omóplato Izq | • Espina Omóplato Izq • LVR • FC |
- | FC × (X_espina - LVR) |
| 8 | Punto Ángulo Inferior Omóplato Izq | • Ángulo Inf Omóplato Izq • LVR • FC |
- | FC × (X_angulo - LVR) |
| 9 | Punto Interno Espina Omóplato Der | • Espina Omóplato Der • LVR • FC |
- | FC × (X_espina - LVR) |
| 10 | Punto Ángulo Inferior Omóplato Der | • Ángulo Inf Omóplato Der • LVR • FC |
- | FC × (X_angulo - LVR) |
Región: Cintura Pélvica¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula |
|---|---|---|---|---|
| 11 | Ángulo de Inclinación Pelvis | • EIPS Izquierda • EIPS Derecha |
- | angle(eips_izq, eips_der) |
Región: Miembro Inferior¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula |
|---|---|---|---|---|
| 12 | Ángulo Calcáneo Izquierdo | • Tendón Aquiles Izq • Calcáneo Izq • Punto Medio Pliegue Poplíteo Izq |
Auto-estimable | angle(aquiles, calcaneo, popliteo) |
| 13 | Ángulo Calcáneo Derecho | • Tendón Aquiles Der • Calcáneo Der • Punto Medio Pliegue Poplíteo Der |
Auto-estimable | angle(aquiles, calcaneo, popliteo) |
⚡ OPTIMIZACIÓN: Los puntos poplíteos se pueden auto-estimar si solo se marca Aquiles + Calcáneo.
Total marcadores Vista Posterior: 16 marcadores + 2 calibración + LVR = 19 puntos
👁️ VISTA LATERAL (Perfil Derecho)¶
Región: Cérvico-Cefálica¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula | Código MATLAB |
|---|---|---|---|---|---|
| 1 | 🔴 Ubicación Sagital de Cabeza | • Tragus • LVR • FC |
- | FC × (X_tragus - LVR) |
Línea 446 |
| 2 | Tangentes Occipital - Dorso | • Occipital • Tangente Dorso • FC |
- | FC × (X_occipital - X_dorso) |
Línea 483 |
| 3 | Lordosis Cervical | • C7 • Tangente Dorso • FC |
- | FC × (X_c7 - X_dorso) |
Línea 508 |
Región: Tronco - Columna¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula | Código MATLAB |
|---|---|---|---|---|---|
| 4 | Tangentes Dorso - Sacro | • Tangente Dorso • Punto Sacro • FC |
- | FC × (X_dorso - X_sacro) |
Línea 637 |
| 5 | Lordosis Lumbar | • Apex Lumbar • Punto Sacro • FC |
- | FC × (X_apex - X_sacro) |
Línea 672 |
Región: Cintura Escapular¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula | Código MATLAB |
|---|---|---|---|---|---|
| 6 | Alineación Sagital Hombro | • Acromion • LVR • FC |
- | FC × (X_acromion - LVR) |
Línea 970 |
Región: Miembro Superior¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula | Código MATLAB |
|---|---|---|---|---|---|
| 7 | Ángulo de Codo | • Acromion • Epicóndilo • Base 3er Metacarpiano |
- | angle(acromion, epicondilo, meta) |
Líneas 1034-1037 |
Región: Cintura Pélvica¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula | Código MATLAB |
|---|---|---|---|---|---|
| 8 | Traslación Pélvica (Ilíaco) | • Tubérculo Ilíaco • LVR • FC |
- | FC × (X_iliaco - LVR) |
Línea 1151 |
| 9 | Traslación Pélvica (Trocánter) | • Trocánter Mayor • LVR • FC |
- | FC × (X_trocanter - LVR) |
Línea 1106 |
| 10 | Basculación Pélvica Sagital | • Tubérculo Ilíaco • Trocánter Mayor |
- | angle(tuberculo, trocanter) |
Líneas 1333-1357 |
Región: Miembro Inferior¶
| # | Variable | Marcadores Mínimos | Opcional | Fórmula | Código MATLAB |
|---|---|---|---|---|---|
| 11 | Ángulo de Rodilla | • Trocánter Mayor • Tubérculo Cóndilo Externo • Borde Anterior Maléolo |
- | angle(trocanter, condilo, maleolo) |
Líneas 1384-1414 |
| 12 | Ángulo Tibiotarsiano | • Tubérculo Cóndilo Externo • Borde Anterior Maléolo • Base 5to Metatarsiano |
- | angle(condilo, maleolo, metatarsiano) |
Líneas 1474-1514 |
Total marcadores Vista Lateral: 13 marcadores + 2 calibración + LVR = 16 puntos
👁️ VISTA LATERAL (Perfil Izquierdo)¶
Las variables y marcadores son IDÉNTICOS a Perfil Derecho, solo que medidos del lado izquierdo.
NOTA: Algunos ángulos pueden tener signos opuestos debido a la orientación de la imagen.
🔴 CASO PROBLEMA: Ubicación Sagital de Cabeza¶
El Problema Reportado¶
Situación: En evaluación de exoesqueleto (perfil izquierdo), se marcaban: - ✅ Tragus (oreja) - ✅ LVR (línea vertical de referencia)
Resultado: ❌ "Ubicación Sagital de Cabeza" no aparecía
Causa Raíz¶
La variable "Ubicación Sagital de Cabeza" se calcula como:
% Línea 446 de InterfazMedicionPerfilDerechoJulio2024.m
DistanciaTragus = handles.FC * (XTRAGUS - handles.Vx1);
Donde:
- FC = Factor de Calibración = 10 / D12
- XTRAGUS = Coordenada X del Tragus
- Vx1 = Línea Vertical de Referencia (LVR)
Por Qué No Funcionaba¶
Marcadores presentes:
- ✅ Tragus → XTRAGUS disponible
- ✅ LVR → Vx1 disponible
Marcadores FALTANTES:
- ❌ Punto de Calibración 1 → D12 = 0
- ❌ Punto de Calibración 2 → D12 = 0
Resultado:
FC = 10 / 0 # ¡Error! División por cero
# O bien: FC queda en valor por defecto = 0
DistanciaTragus = 0 * (X_tragus - LVR) = 0
Solución¶
Para calcular "Ubicación Sagital de Cabeza" se necesitan:
- ✅ Tragus (el marcador de la oreja)
- ✅ LVR (línea vertical de referencia)
- ✅ FC (factor de calibración) → REQUIERE 2 puntos de calibración separados 10 cm
Marcadores mínimos totales:
• Tragus
• LVR
• Punto Calibración 1
• Punto Calibración 2 (separado 10 cm del punto 1)
Total: 4 elementos (2 marcadores + 2 calibración)
Verificación en Código¶
MATLAB (líneas 439-449):
if (TRAGUSDER ~= 0)
XTRAGUS = handles.matXY(TRAGUSDER,1);
YTRAGUS = handles.matXY(TRAGUSDER,2);
% Validación del Factor de Calibración
if handles.FC > 0
DistanciaTragus = handles.FC * (XTRAGUS - handles.Vx1);
handles.DistanciaTragus = DistanciaTragus;
else
handles.DistanciaTragus = 000; % ← "Punto no visible"
end
end
⚠️ Si FC = 0, el resultado es 000 = "Punto no visible"
🔴 CASO PROBLEMA 2: Lordosis Lumbar (Error x10)¶
El Problema de los "Datos Locos"¶
Situación: Evaluadores 4 y 8 obtuvieron lordosis lumbar de 51 cm (debería ser ~5 cm)
Variable afectada:
% Línea 672
DistanciaApexSacro = handles.FC * (XAPEXLUMBAR - handles.Xsacro);
Causa Raíz¶
Marcadores esperados:
- ✅ Apex Lumbar → XAPEXLUMBAR disponible
- ❌ "Punto Sacro" (nombre EXACTO requerido)
Marcadores usados por los evaluadores: - ❌ "Espina Ilíaca Posterosuperior" - ❌ "Espina Ilíaca Posteroinferior"
Resultado:
% Código MATLAB espera exactamente "Punto Sacro"
switch handles.lista
case 'Punto Sacro'
handles.Xsacro = x1; % Solo se asigna si el nombre es EXACTO
end
% Si el nombre no coincide:
handles.Xsacro = 0 % ← Queda en cero!
% Entonces:
DistanciaApexSacro = FC * (XAPEXLUMBAR - 0)
DistanciaApexSacro = FC * XAPEXLUMBAR % ← Valor inflado x10!
Solución¶
Marcadores requeridos para Lordosis Lumbar:
• Apex Lumbar
• "Punto Sacro" (NOMBRE EXACTO, case-sensitive)
• FC
⚠️ NOMBRES DEBEN SER EXACTOS - MATLAB usa switch case estricto
📊 Tabla Resumen: Evaluaciones Parciales¶
Caso de Uso 1: Solo Rodillas¶
Vista: Anterior Variables: Ángulo Q Derecho e Izquierdo
Marcadores mínimos:
✅ EIAS Izquierda
✅ EIAS Derecha
✅ Centro Rótula Izquierda
✅ Centro Rótula Derecha
✅ TAT Izquierda
✅ TAT Derecha
✅ Punto Calibración 1
✅ Punto Calibración 2
✅ LVR
Total: 9 puntos (6 marcadores + 2 calibración + LVR)
Caso de Uso 2: Solo Posición de Cabeza (Perfil)¶
Vista: Lateral Derecha Variable: Ubicación Sagital de Cabeza
Marcadores mínimos:
✅ Tragus
✅ Punto Calibración 1
✅ Punto Calibración 2
✅ LVR
Total: 4 puntos
⚠️ ADVERTENCIA: Sin los puntos de calibración, FC = 0 y la variable aparecerá como "Punto no visible"
Caso de Uso 3: Evaluación de Columna (Posterior)¶
Vista: Posterior Variables: Desbalance coronal C7, T3, T7, T12, L5
Marcadores mínimos:
✅ C7
✅ T3
✅ T7
✅ T12
✅ L5
✅ Punto Calibración 1
✅ Punto Calibración 2
✅ LVR
Total: 8 puntos (5 vértebras + 2 calibración + LVR)
Caso de Uso 4: Solo Hombros (Anterior)¶
Vista: Anterior Variable: Ángulo de Inclinación Hombros
Marcadores mínimos:
✅ Acromion Izquierdo
✅ Acromion Derecho
✅ Punto Calibración 1
✅ Punto Calibración 2
✅ LVR (no estrictamente necesario para ángulos)
Total: 4-5 puntos
💡 NOTA: Para variables de ángulo (no distancias), la LVR NO es necesaria. Solo se necesita FC si el ángulo usa distancias.
⚠️ Reglas Críticas de Validación¶
1. Marcador Faltante → "Punto No Visible"¶
MATLAB (ejemplo línea 426-430):
if (TRAGUSDER == 0)
% No se encontró el marcador
handles.DistanciaTragus = 000; % "Punto no visible"
end
Python (debería hacer):
if tragus is None or fc == 0:
return {
"value": None,
"diagnosis": "Punto no visible",
"error": "Marcador faltante o FC=0"
}
2. Nombres de Marcadores DEBEN Ser Exactos¶
MATLAB usa switch case estricto:
switch handles.lista
case 'Punto Sacro' % ← EXACTO
handles.Xsacro = x1;
case 'Apex Lumbar' % ← EXACTO
XAPEXLUMBAR = x1;
end
Si el nombre no coincide: Variable queda en 0 → Cálculos incorrectos
Solución: Usar los nombres EXACTOS definidos en marker-definitions.ts
3. Factor de Calibración (FC) es OBLIGATORIO¶
Para TODAS las variables de distancia (cm), se requiere FC > 0.
Cálculo del FC:
D12 = sqrt((x2-x1)² + (y2-y1)²) # Distancia entre puntos de calibración
FC = 10.0 / D12 # cm/pixel
Sin FC válido (FC = 0): - ❌ Todas las distancias = 0 - ❌ Aparece como "Punto no visible"
🎓 Ejemplo Completo: Evaluación Solo de Rodillas¶
Objetivo¶
Medir solo Ángulo Q (rodillas) sin marcar todo el cuerpo.
Paso 1: Preparar imagen¶
- Foto del paciente de frente (vista anterior)
- Importante: Incluir regla o patrón de calibración de 10 cm
Paso 2: Marcar puntos de calibración¶
1. Punto Calibración 1: (x1, y1) ← Inicio de regla 10 cm
2. Punto Calibración 2: (x2, y2) ← Fin de regla 10 cm
Paso 3: Marcar línea vertical de referencia¶
3. LVR: Click en punto vertical de referencia (ej: línea en fondo)
Paso 4: Marcar puntos de rodillas¶
4. EIAS Izquierda
5. EIAS Derecha
6. Centro Rótula Izquierda
7. Centro Rótula Derecha
8. TAT Izquierda (Tuberosidad Anterior Tibia)
9. TAT Derecha
Paso 5: Calcular¶
✅ Ángulo Q Izquierdo = calculado
✅ Ángulo Q Derecho = calculado
❌ Otras variables = "Punto no visible"
Total marcadores: 9 puntos (en lugar de 20 para vista anterior completa)
🛡️ Validación de Marcadores en Código¶
Verificación Actual en Python¶
# api.py, línea ~700
def _get_point(self, key: str) -> Tuple[float, float]:
"""Extract point from markers dict"""
if key not in self.markers:
raise ValueError(f"Missing required marker: {key}") # ← CORRECTO ✅
# ...
Estado: ✅ YA VALIDA que el marcador existe
Verificación Recomendada para FC¶
def calculate_distance_variable(marker_x, lrv_x, fc):
"""
Calcula variable de distancia con validación
"""
# VALIDAR: FC debe ser > 0
if fc <= 0:
return {
"value": None,
"diagnosis": "Punto no visible",
"error": "Factor de calibración inválido (FC=0). Marque puntos de calibración."
}
# VALIDAR: Marcador debe existir
if marker_x is None:
return {
"value": None,
"diagnosis": "Punto no visible",
"error": "Marcador faltante"
}
# Calcular
distance = fc * (marker_x - lrv_x)
return {
"value": distance,
"diagnosis": diagnose(distance),
"error": None
}
Acción requerida: Agregar esta validación a TODAS las funciones de cálculo.
📋 Checklist de Implementación¶
Para Desarrolladores¶
Cuando agregues una nueva variable, asegúrate de:
- [ ] Documentar marcadores mínimos en esta tabla
- [ ] Validar que marcadores existen antes de calcular
- [ ] Validar que FC > 0 para variables de distancia
- [ ] Retornar "Punto no visible" si falta algún marcador
- [ ] Retornar mensaje claro de qué falta (ej: "Falta Punto Sacro")
- [ ] Agregar test con marcador faltante
- [ ] Agregar test con FC = 0
Para Usuarios¶
Antes de intentar calcular una variable:
- [ ] Verificar marcadores requeridos en esta tabla
- [ ] Marcar primero los puntos de calibración (SIEMPRE)
- [ ] Marcar la LVR
- [ ] Marcar los marcadores específicos de la variable
- [ ] Usar nombres EXACTOS de marcadores (case-sensitive en MATLAB)
🔧 Mejoras Propuestas¶
1. Validación Preventiva en Frontend¶
// Antes de permitir "Calcular"
function validateRequiredMarkers(view: string, variables: string[]): ValidationResult {
const missingMarkers = [];
// Siempre requeridos
if (!hasCalibrationPoints()) {
missingMarkers.push("Puntos de Calibración (2)");
}
if (!hasLVR()) {
missingMarkers.push("Línea Vertical de Referencia");
}
// Por variable
for (const variable of variables) {
const required = MARCADORES_POR_VARIABLE[view][variable];
for (const marker of required) {
if (!hasMarker(marker)) {
missingMarkers.push(`${marker} (para ${variable})`);
}
}
}
return {
valid: missingMarkers.length === 0,
missing: missingMarkers
};
}
2. Mensajes Claros al Usuario¶
// En lugar de:
❌ "Punto no visible"
// Mostrar:
✅ "No se puede calcular 'Ubicación Sagital de Cabeza'"
"Marcadores faltantes:"
" • Punto de Calibración 1"
" • Punto de Calibración 2"
"Por favor marque ambos puntos separados exactamente 10 cm"
3. Sugerencias de Evaluación Parcial¶
// Botón en UI: "Evaluar Solo Rodillas"
// Auto-selecciona en la tabla:
const marcadoresMinimosRodillas = [
"EIAS Izquierda",
"EIAS Derecha",
"Centro Rótula Izquierda",
"Centro Rótula Derecha",
"TAT Izquierda",
"TAT Derecha",
"Punto Calibración 1",
"Punto Calibración 2",
"LVR"
];
// Y oculta los demás marcadores de la lista
📖 Referencias Rápidas¶
Archivo → Variable → Marcadores¶
calculations.py (Vista Anterior):
angle_with_horizontal() → Tragus Izq + Tragus Der
horizontal_distance_cm() → Marcador + LVR + FC
trunk_angle() → Sínfisis Pubiana + Escotadura Esternal
pelvis_angle() → EIAS Izq + EIAS Der
q_angle() → TAT + Centro Rótula + EIAS
calculations_lateral.py (Vista Perfil):
head_angle_horizontal() → Tragus + Apex Cervical
trunk_angle_vertical() → Apex Cervical + Apex Lumbar
elbow_angle() → Acromion + Epicóndilo + Metacarpiano
knee_angle() → Trocánter + Cóndilo + Maléolo
calculations_posterior.py (Vista Posterior):
calcaneo_angle_left() → Aquiles Izq + Calcáneo Izq + Poplíteo Izq
calcaneo_angle_right() → Aquiles Der + Calcáneo Der + Poplíteo Der
coronal_balance_c7() → C7 + LVR + FC
coronal_balance_t7() → T7 + LVR + FC
coronal_balance_l5() → L5 + LVR + FC
pelvis_angle_posterior() → EIPS Izq + EIPS Der
head_angle_posterior() → Lóbulo Izq + Lóbulo Der
🎯 Resumen Ejecutivo¶
| Vista | Variables Totales | Marcadores Mínimos (completo) | Marcadores para 1 variable (mínimo) |
|---|---|---|---|
| Anterior | 15 variables | 20 puntos | 4-6 puntos (depende de variable) |
| Posterior | 16 variables | 19 puntos | 4-6 puntos |
| Perfil Derecho | 13 variables | 16 puntos | 4-5 puntos |
| Perfil Izquierdo | 13 variables | 16 puntos | 4-5 puntos |
Regla de oro: Puntos de Calibración + LVR son OBLIGATORIOS para TODAS las evaluaciones (incluso parciales).
✅ Acción Requerida¶
- ✅ Documentar marcadores mínimos (este documento)
- ⏳ Validar en código que marcadores existen antes de calcular
- ⏳ Mensajes claros cuando faltan marcadores
- ⏳ Tests con marcadores faltantes
- ⏳ UI helpers para evaluaciones parciales (botones: "Solo Rodillas", "Solo Columna", etc.)
Última actualización: 2025-12-30 Mantenedor: Luis Arancibia Fuente: Análisis de código MATLAB + Python + casos reales Dra. Oleari