49 lines
1.3 KiB
Python
49 lines
1.3 KiB
Python
"""Threshold-based temperature profile segmentation into Ramp/Soak/Cool phases."""
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass
|
|
class DataSegment:
|
|
"""A contiguous segment of the temperature profile."""
|
|
label: str
|
|
start_frame: int
|
|
end_frame: int
|
|
avg_temp: float
|
|
|
|
|
|
def segment_profile(avg_temps: list[float], threshold: float = 40.0) -> list[DataSegment]:
|
|
"""Scan average temperatures and identify Ramp/Soak/Cool phases.
|
|
|
|
Args:
|
|
avg_temps: Per-frame average temperatures.
|
|
threshold: Temperature threshold (°C) defining Soak entry/exit.
|
|
|
|
Returns:
|
|
List of DataSegment objects covering the entire profile.
|
|
"""
|
|
if not avg_temps:
|
|
return []
|
|
|
|
segments: list[DataSegment] = []
|
|
n = len(avg_temps)
|
|
i = 0
|
|
|
|
while i < n and avg_temps[i] < threshold:
|
|
i += 1
|
|
if i > 0:
|
|
avg = sum(avg_temps[:i]) / i
|
|
segments.append(DataSegment("Ramp", 0, i - 1, round(avg, 2)))
|
|
|
|
while i < n:
|
|
start = i
|
|
above = avg_temps[i] >= threshold
|
|
while i < n and (avg_temps[i] >= threshold) == above:
|
|
i += 1
|
|
label = "Soak" if above else "Cool"
|
|
count = i - start
|
|
avg = sum(avg_temps[start:i]) / count
|
|
segments.append(DataSegment(label, start, i - 1, round(avg, 2)))
|
|
|
|
return segments
|