스마트워치 센서 기반 정량적 운동 분석 · Clinical Decision Support
파킨슨병 환자를 진단·평가하는 의사를 위한 Dash + Plotly 기반 interactive 대시보드입니다. 스마트워치(가속도계/자이로스코프) 센서 데이터에서 추출한 movement feature를 정량적으로 시각화하여, 의사가 더 정확하고 일관된 판단을 내릴 수 있도록 지원합니다.
Live Demo: https://pd-dashboard-ten.vercel.app
이 대시보드는 AI 자동 진단 시스템이 아닙니다.
의사가 이미 알고 있는 임상적 판단을 정량적 근거로 뒷받침하는 도구입니다.
| 기존 평가 방식 | 이 대시보드가 제공하는 것 |
|---|---|
| "떨림이 좀 있는 것 같다" | Tremor power: 0.72 (상위 92 percentile) |
| "리듬이 불규칙한 것 같다" | Rhythm irregularity CV: 0.38 |
| "지난번보다 나빠진 것 같다" | Tremor +15.2%, Amplitude -8.3% (방문 대비) |
| "UPDRS 몇 점으로 할까" | Sensor 기반 추정: 3.4 Finger Tapping → Est. 2.8/4 |
| 영역 | 도구 |
|---|---|
| Dashboard Framework | Dash (by Plotly) |
| Visualization | Plotly Express + Plotly Graph Objects |
| Backend | Dash callback 기반 Python backend |
| Data Processing | pandas, numpy, scipy |
| Data Storage | SQLite + DuckDB + CSV/JSON |
| Metadata DB | SQLite (DB/storage/sqlite/clinical_meta.db) |
| Analytics DB | DuckDB (DB/storage/duckdb/features.duckdb) |
| Server | Dash 내장 Flask server |
┌──────────────────────────────────────────┐
│ Frontend Layer │
│ Dash Layout + Plotly Interactive Charts │
│ dcc.Dropdown, dcc.Tabs, dcc.Graph │
├──────────────────────────────────────────┤
│ Backend Layer │
│ Python Callbacks │
│ Feature Engineering (CV, Asymmetry 등) │
│ UPDRS Score Estimation │
│ Normative Z-score 계산 │
├──────────────────────────────────────────┤
│ Data Layer │
│ SQLite: patient/visit/task/label metadata │
│ DuckDB: frame-level video features │
│ CSV/JSON: ingestion source (PADS/TULIP) │
│ DB bootstrap: DB/sql + DB/scripts │
└──────────────────────────────────────────┘
배포된 대시보드는 아래에서 바로 확인할 수 있습니다:
https://pd-dashboard-ten.vercel.app
로컬에서 실행하려면 아래 단계를 따르세요.
- Python 3.9 이상 (Python 버전 확인:
python3 --version) - pip (Python 패키지 관리자)
- 저장소에 포함된
pads_matched/,labels_csv_files/,visual-consensus-dashboard/data/데이터 파일
git clone https://github.com/sungmoonie/PD-Dashboard.git
cd PD-Dashboard프로젝트별 패키지 충돌을 방지하기 위해 가상환경 사용을 권장합니다.
# 가상환경 생성
python3 -m venv venv
# 가상환경 활성화
# macOS / Linux:
source venv/bin/activate
# Windows (PowerShell):
.\venv\Scripts\Activate.ps1
# Windows (CMD):
.\venv\Scripts\activate.bat활성화되면 터미널 앞에
(venv)가 표시됩니다.
pip install -r requirements.txtcd visual-consensus-dashboard
python3 app.py실행에 성공하면 아래와 같은 메시지가 출력됩니다:
Dash is running on http://127.0.0.1:8050/
Vercel에서는 vercel.json이 모든 요청을 Dash 앱의 Python serverless entry point로 라우팅합니다.
- Serverless entry point:
visual-consensus-dashboard/api/index.py - WSGI callable:
app = dash_app.server api/index.py는src.*import와data/,assets/상대경로가 동작하도록visual-consensus-dashboard/를 Python path와 working directory에 맞춥니다.
| 증상 | 원인 | 해결 방법 |
|---|---|---|
command not found: python |
macOS/Linux에서는 python3이 기본 |
python 대신 python3 사용 |
Address already in use (Port 8050) |
이전 실행이 아직 종료되지 않음 | lsof -i :8050으로 PID 확인 후 kill <PID> |
ModuleNotFoundError |
패키지 미설치 또는 가상환경 미활성화 | pip install -r requirements.txt 재실행, 가상환경 활성화 확인 |
FileNotFoundError for pads_matched or labels_csv_files |
앱 실행 위치가 잘못되었거나 데이터 폴더가 없음 | 저장소 루트에 데이터 폴더가 있는지 확인 후 visual-consensus-dashboard/에서 실행 |
PD-Dashboard/
├── README.md
├── requirements.txt ← 대시보드 실행용 Python 패키지
├── vercel.json ← Vercel 라우팅 및 Python runtime 설정
│
├── visual-consensus-dashboard/
│ ├── app.py ← Dash 앱 실행 + callback 정의
│ ├── api/
│ │ └── index.py ← Vercel serverless entry point
│ ├── assets/
│ │ └── style.css ← 대시보드 스타일
│ ├── data/
│ │ └── video_analysis.json ← 앱에서 사용하는 video analysis JSON
│ └── src/
│ ├── data_loader.py ← PADS/TULIP/label 데이터 로드
│ ├── feature_engineering.py ← 지표 계산 함수
│ ├── figures.py ← Plotly figure 생성
│ └── layout.py ← 5-tab 대시보드 레이아웃
│
├── pads_matched/
│ ├── by_tulip/ ← TULIP별 PADS 환자/설문/시계열/video feature
│ ├── configs/
│ └── scripts/
│
├── labels_csv_files/ ← clinician UPDRS label CSV
│
└── DB/
├── README.md ← DB bootstrap guide
├── sql/ ← SQLite/DuckDB schema
├── scripts/ ← ingestion scripts
└── requirements.txt ← DB bootstrap dependency
- 출처: PhysioNet (
parkinsons-disease-smartwatch/1.0.0) - 참여자: 469명 (PD 환자, 감별진단군, 건강대조군)
- 센서: 양손 Apple Watch Series 4 (가속도계 + 자이로스코프, 100Hz)
- Motor Task 11가지: Resting, Arm lifting, Finger touching, Gait 등
- 활용: 정량적 motor profile 생성, 좌우 비대칭 분석, rhythm/amplitude 분석
- 출처: Zenodo (record 14262223)
- 현재 매핑된 대상자: 12명 (PD 환자 + 건강대조군)
- 영상: 6대 카메라 멀티뷰 synchronized 영상
- 활용: Toe tapping / resting 영상 feature, multi-camera video review, 3D keypoint trajectory 확장
현재 대시보드는 데모 CSV를 생성하지 않고, 저장소 내 real-data scaffold를 직접 읽습니다.
| 경로 | 역할 |
|---|---|
pads_matched/by_tulip/README_mapping.csv |
TULIP ID와 PADS subject ID 매핑 |
pads_matched/by_tulip/*/patients/*.json |
환자 인구통계 및 진단 정보 |
pads_matched/by_tulip/*/questionnaire/*.json |
NMS 설문 응답 |
pads_matched/by_tulip/*/movement/timeseries/*.txt |
Apple Watch sensor time-series |
pads_matched/by_tulip/*/videos_feature/*/Camera*_features.csv |
video-derived feature |
pads_matched/by_tulip/*/videos_feature/*/Camera*_joint.csv |
joint/keypoint feature |
labels_csv_files/*.csv |
3명 clinician의 UPDRS label |
visual-consensus-dashboard/data/video_analysis.json |
대시보드용 video analysis JSON |
목적: 선택한 환자의 전반적인 motor/non-motor 상태를 한눈에 파악
구성 요소:
- 인구통계/진단 정보: TULIP ID, PADS ID, 나이, 성별, 손잡이, BMI, disease duration
- NMS 요약: questionnaire에서 보고된 non-motor symptoms
- Motor phenotype summary: reference proximity, asymmetry, phenotype interpretation
- Bilateral matrix: aligned tasks 중심의 좌우 feature 비교
- Asymmetry group compare: reference group 대비 비대칭 패턴
임상 활용: 진료 시작 시 환자의 전체 상태를 빠르게 파악하는 "첫 화면"
목적: 반복 운동과 안정 시 떨림에서 tremor, rhythm, amplitude 변화를 정량 분석
시각화:
- Tremor power bar chart
- Tremor frequency band breakdown
- Spectral fingerprint
- Rhythm ladder / interval variability
- Amplitude decrement
- 좌우 wrist raw time-series
임상 활용: "불규칙해 보인다", "점점 작아지는 것 같다", "떨림이 강하다"는 관찰을 숫자와 그래프로 확인
목적: TULIP multi-camera 영상과 video-derived feature를 함께 검토
구성 요소:
- Toe tapping left/right, resting & hand tremor 영상 선택
- Camera 1-6 선택
- Cloudflare R2 CDN video playback
- Video feature 기반 left/right comparison, interval distribution, tremor spectrogram, symmetry trend
임상 활용: 센서 기반 feature와 실제 영상을 같은 화면에서 검토하여 판단 근거를 확인
목적: 선택 환자의 motor feature가 PD/Healthy reference group 중 어느 쪽에 가까운지 비교
시각화:
- Proximity gauge
- 2D proximity map
- Task/metric별 selected patient vs group distribution
핵심 방법: aligned task feature vector를 z-score normalized distance로 비교하여 PD-like / Healthy-like proximity를 산출
목적: 환자별 주요 소견과 clinician decision workspace를 한 화면에서 정리
구성 요소:
- Motor phenotype verdict
- 주요 feature별 PD-like / Healthy-like findings
- Summary radar
- Aligned task feature table
- Decision Workspace (우측 패널): UPDRS Motor Assessment 입력, Save/Reset Decision, clinician majority comparison, Export All Decisions (JSON)
중요: 이 대시보드는 clinician decision support 도구이며, 최종 scoring과 진단은 임상 소견에 따릅니다.
| Feature | 설명 | 임상 의미 |
|---|---|---|
| Tremor Power | 가속도 신호의 4-6Hz 대역 파워 | 안정 시/자세 유지 시 떨림 강도 |
| Amplitude Reduction | 반복 동작에서 진폭이 점차 감소하는 정도 | Bradykinesia의 핵심 지표 (decrement) |
| Rhythm Irregularity | 반복 동작 간격의 변동계수 (CV) | 운동 리듬의 불규칙성 |
| Left-Right Asymmetry | 좌우 사지 간 movement feature 차이 | PD의 lateralized impairment |
| Motion Instability | 신호의 jerkiness (가속도 미분의 변동) | 움직임의 매끄러움 저하 |
| Task | 설명 | 대응 UPDRS 항목 |
|---|---|---|
| Toe Tapping / Entrainment | 발가락을 빠르게 반복 두드리기 | 3.7 |
| Resting / Relaxed | 안정 시 손 떨림 및 움직임 관찰 | 3.17 |
| Finger Tapping | 엄지와 검지를 빠르게 반복 두드리기 | 3.4 |
| Hand Open/Close | 손을 빠르게 반복 펴기/쥐기 | 3.5 |
| Gait | 일정 거리를 걷기 | 3.10 |
| Touch Nose | 손가락으로 코를 반복 터치 | 3.8 (proxy) |
현재 대시보드는 Toe Tapping (Entrainment) 과 Resting (Relaxed) 를 aligned tasks로 두고 핵심 비교와 요약을 구성합니다. 다른 PADS task는 데이터 로더와 feature extraction 맥락에서 활용될 수 있습니다.
- SQLite metadata DB:
patients,visits,tasks,video_assets,clinical_labels활용 - DuckDB analytics DB: frame-level video/joint/timeseries feature와 task summary 활용
- Serverless production storage: Vercel runtime에서는 local DB persistence에 의존하지 않고 외부 persistent storage/DB 사용
- 환자 간 비교 기능 (두 환자를 나란히 비교)
- PDF 리포트 자동 생성
- 실시간 센서 데이터 스트리밍 연결
- 약물 복용 전/후 비교 (ON/OFF state)