Filtering a trace without filling recording gaps¶
filter_trace optionally applies a median filter to signed measurement values
on their original time coordinates. It neither estimates a rhythm nor removes a
baseline. Filtering is an analysis choice to audit; it does not establish accuracy.
import circadian_workbench as cw
result = cw.filter_trace(
[0., 0.1, 2., 3., 8.], [0., 100., 2., None, -1.],
filtering={"method": "median", "window_hours": 1.,
"max_gap_hours": 3., "min_observations": 1},
)
assert result.data["values"] == [50., 50., 2., None, -1.]
Choose filtering={"method": "none"} for unchanged finite values and missing
positions. The median choice requires positive window_hours and max_gap_hours;
min_observations defaults to 1 and must be a positive integer. All times and
windows use hours; original value units and signs are retained.
Either method accepts omit_intervals_hours, a list of closed [start, end]
intervals on the original time coordinates. Those positions become missing before
filtering and split observed segments. For an observation-sensitivity audit, use
{"method": "none", "omit_intervals_hours": [[20., 30.]]} to create an altered
raw input, then apply each candidate's complete preprocessing and analysis afresh.
The result records the omitted mask separately from source_missing; it retains
original values in the observations table and never removes or shifts timestamps.
The median uses an inclusive centered physical-time window, with equal weight per observation. It uses NumPy's median convention for odd and even numbers of contributing observations. This is not a fixed number of rows or an occupancy-time-weighted average. Partial edge windows are allowed only when the declared observation minimum is met.
Every unavailable input value splits a segment. Consecutive timestamps farther
apart than max_gap_hours also split segments. A filter window never crosses one
of those boundaries. Non-finite inputs remain unavailable; insufficient windows
produce an additional missing output with its own reason. Times must be finite,
unique and increasing. There is no interpolation, zero filling or compression
of elapsed time, and no assumed daily or sinusoidal rhythm.
The completed result retains hours, filtered values, source_missing,
missing, settings and an observations table with original value/kind, segment,
contributor count, first/last contributor index and rejection reason. It also
provides the standard run record and equivalent script. Array positions stay
aligned, including unavailable rows. The action performs no analysis or rendering
on read-back.