import numpy as np
def find_two_peak_indices_mad_pos(x: np.ndarray, k: float = 6.0) -> tuple[int, int]:
"""
양(+) 스파이크만 존재하는 DC 이동 편차 데이터에서
MAD 기반 임계값으로 2개의 피크 이벤트를 찾고,
각 이벤트의 피크 인덱스 2개를 시간순으로 반환합니다.
threshold = median(x) + k * 1.4826 * MAD
"""
x = np.asarray(x, dtype=float)
n = x.size
if n < 2:
raise ValueError("data too short")
m = np.median(x)
dev = x - m
mad = np.median(np.abs(dev))
scale = 1.4826 * mad
if scale == 0:
scale = 1e-12 # 거의 평탄한 데이터 보호
thr = k * scale
mask = dev > thr
if not mask.any():
raise ValueError("no peak candidates found (threshold too high)")
# 연속 구간(run) start/end
d = np.diff(mask.astype(np.int8))
starts = np.where(d == 1)[0] + 1
ends = np.where(d == -1)[0] + 1
if mask[0]:
starts = np.r_[0, starts]
if mask[-1]:
ends = np.r_[ends, n]
runs = list(zip(starts.tolist(), ends.tolist()))
if len(runs) < 2:
raise ValueError(f"found {len(runs)} event(s); need at least 2")
# run별 최대값 기준으로 강한 이벤트 2개 선택(같은 피크 중복 방지)
strengths = np.array([x[s:e].max() for s, e in runs])
top2_idx = np.argpartition(strengths, -2)[-2:]
top2_runs = [runs[i] for i in top2_idx]
top2_runs.sort(key=lambda se: se[0]) # 시간순
# 각 run에서 피크 인덱스
p1 = top2_runs[0][0] + int(np.argmax(x[top2_runs[0][0]:top2_runs[0][1]]))
p2 = top2_runs[1][0] + int(np.argmax(x[top2_runs[1][0]:top2_runs[1][1]]))
return int(p1), int(p2)