# RodentMealScope (로덴트밀스코프)

> 설치류 섭식 행동을 **식사(meal) 미세구조**로 분해하는 비만/신경내분비 동물실험 분석 도구

- **도메인**: 비만 (Obesity)
- **카테고리**: 동물실험 도구 (animal experiment tool)
- **형태**: 단독 실행형 Streamlit 앱 · 완전 오프라인 동작

> ⚠️ **참고용·연구용 (for reference / research use only)**
> 본 도구는 연구 보조 목적의 분석 도구입니다. 산출 결과는 임상적 진단·치료
> 판단의 근거로 사용할 수 없으며, 모든 해석은 연구자의 책임 하에 검증되어야
> 합니다. 본 저장소의 데이터는 전부 합성(synthetic) 데이터입니다.

---

## 무엇을 하는가

비만·식욕 연구 동물실험에서 자동 급이기가 기록하는 **원자료 섭식 이벤트 로그**는
초 단위의 수많은 섭취 이벤트로 구성되어 있어, 그대로는 "이 약물이 식사를 어떻게
바꾸었는가"를 알기 어렵습니다. RodentMealScope는 이 원자료를 받아:

1. 여러 하드웨어 포맷을 **공통 스키마로 정규화**하고
2. 데이터로부터 **객관적인 식사 기준**을 도출한 뒤
3. 이벤트를 식사 단위로 묶어 **표준 미세구조 지표**를 계산하고
4. **일주기(circadian)** 패턴으로 분해하며
5. **코호트 통계**와 약물 **기전 분류**까지 산출합니다.

이를 통해 "총 섭취량은 같은데 식사를 더 작게 자주 먹는지", "식사 크기는 그대로인데
횟수가 줄었는지" 같은 **포만(satiation) vs 포만감(satiety) 기전**을 구분할 수 있습니다.

---

## 5가지 핵심 기능

| # | 기능 | 설명 |
|---|------|------|
| 1 | **다중 하드웨어 이벤트 정규화** | BioDAQ / FED3 / 자동급이기 / lickometer / PhenoMaster export를 공통 스키마(animal_id, timestamp, intake_amount, licks, bout)로 변환. 결측·노이즈(흘림 spillage, 이중계수 double-counting)에 QC 플래그 부여 |
| 2 | **객관적 식사 기준 도출** | 이벤트 간격(intermeal interval)의 **로그-생존곡선 변곡점**(Tolkamp & Kyriazakis 방식)을 검출 → 데이터 기반 권장 식사 분리 간격 자동 산출. 사용자 수동 지정(override)도 지원 |
| 3 | **식사 미세구조 지표** | 식사 크기, 식사 시간, 식사 빈도, 식사간격(IMI), 섭취속도(g/min), 포만비(satiety ratio = IMI / 선행 식사 크기), 첫 식사 잠복기, 총 섭취량 — 개체별·군별 산출 |
| 4 | **일주기 분해** | 암기(dark active) / 명기(light rest) 위상별, zeitgeber-time bin별 섭식 프로파일. 투약 시각 기준 **급성(acute) vs 만성(chronic)** 약물효과 분리 |
| 5 | **코호트 통계 + 리포트** | 군별 미세구조 지표 일원배치 ANOVA / 혼합효과모형(MixedLM). "식사 크기 감소형 vs 식사 빈도 감소형" 기전 분류. Method+Result 섹션(한/영) 내보내기 |

---

## 실행 방법

```bash
# 1) 의존성 설치
pip install -r requirements.txt

# 2) (선택) 합성 샘플 데이터 재생성 — 저장소에 이미 포함되어 있음
python generate_sample_data.py

# 3) 앱 실행
streamlit run app.py
```

브라우저가 자동으로 열립니다. 사이드바에서 **"데모 데이터 불러오기"**를 선택하면
파일 업로드 없이 즉시 전체 기능을 확인할 수 있습니다.

### 자체 데이터 사용
CSV에 최소한 다음 정보가 있으면 됩니다:
- 시각 컬럼 (`timestamp` / `time` / `datetime` 등)
- 섭취량 컬럼 (`intake_amount` / `weightchange` / `dispensed_g` 등) **또는**
  licks 컬럼 **또는** pellet count 컬럼
- (선택) 개체 식별자, 군(group) 컬럼

사이드바에서 하드웨어 포맷을 `auto`로 두면 컬럼명으로 자동 추정합니다.

---

## 파일 구성

```
2026-05-18-2-rodent-meal-scope/
├── app.py                  # Streamlit 앱 (메인 진입점, 5개 탭)
├── meal_core.py            # 순수 파이썬 계산 모듈 (Streamlit 없이 테스트 가능)
├── generate_sample_data.py # 합성 데이터 생성 스크립트 (재현 가능)
├── requirements.txt        # 고정 버전 의존성
├── README.md               # 본 문서
├── QA.md                   # QA 점검 로그
└── data/
    ├── sample_feeder_events.csv    # 메인 합성 로그 (수천 이벤트, 3군 24개체, 5일)
    ├── sample_fed3_export.csv      # FED3 스타일 export 예시
    └── sample_lickometer_export.csv# lickometer 스타일 export 예시
```

---

## 방법론 노트

- **식사 기준(meal criterion)**: 한 식사 안의 짧은 간격과 식사 사이의 긴 간격이
  섞인 분포는 log10(간격) 축에서 이봉성(bimodal)을 띱니다. 두 봉우리 사이의
  골(antimode)이 객관적 식사 경계입니다(Tolkamp & Kyriazakis, 1999 계열 방법).
  분포가 단봉이면 로그-생존곡선의 곡률 최대점을 대안으로 사용합니다.
- **포만비(satiety ratio)**: 선행 식사 1g이 얼마나 오래 다음 식사를 지연시키는지
  (분/g). 포만감의 정량 지표로 쓰입니다.
- **일주기**: 12:12 명암주기 가정, ZT0 = 점등 시각. 설치류는 야행성이므로
  정상 개체는 암기(ZT12–24)에 섭식이 집중됩니다.
- **기전 분류**: 처리군이 대조군 대비 식사 크기를 더 줄였는지 빈도를 더 줄였는지
  비교하여 식욕억제 기전을 분류합니다.

---

## 합성 데이터 출처

본 저장소의 모든 데이터는 `generate_sample_data.py`로 생성된 **합성 데이터**입니다.
실제 동물·환자 데이터가 아니며, 외부 네트워크/API 호출 없이 고정 시드
(`RANDOM_SEED = 20260518`)로 재현 가능합니다. 데이터는 다음을 모사합니다:
- 식사 군집성(burst) → 이봉형 간격 분포
- 야간 집중 섭식 (일주기성)
- 3개 군: Control / Drug-A(식사 크기 감소형) / Drug-B(식사 빈도 감소형)
- QC 검증용 노이즈(흘림, 이중계수) 이벤트

---

## QA 체크리스트

자세한 점검 로그는 [`QA.md`](QA.md) 참조.

- [x] 모든 `.py` 파일 Python 문법 검사 (`ast.parse`)
- [x] `generate_sample_data.py` 실행 → 데이터 파일 생성 확인
- [x] 생성된 CSV를 pandas로 재로딩하여 파싱 확인
- [x] `meal_core.py` 임포트 테스트 (streamlit 불필요)
- [x] `meal_core.py` 기능 실행 — 식사 그룹핑·미세구조 산출값 검증
- [x] `app.py` 문법 검사 (`ast.parse`)
- [x] 오프라인 동작 — 외부 네트워크/API 호출 없음
- [x] 참고용·연구용 면책 문구 포함 (README + 앱 UI)
