You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Tag analysis family has grown a rich set of reduction primitives, but its statistics surface only covers moment statistics. #223 (getStats) was scoped explicitly to N / Min / Max / Mean / Rms / Std — the summing/squaring family — and
deliberately left out order statistics (median, percentiles, IQR). Meanwhile #251
(HistogramWidget: overlay distribution percentiles) shows the domain actively wants
percentiles, but it renders them as a widget display overlay — there is no way to get
percentile values from a Tag programmatically.
IQR (P75 − P25) — robust spread, insensitive to outliers.
These are canonical sensor-analysis / loads / duty-cycle descriptors. Today an engineer must
drop to getXY and hand-roll a sort every time.
Proposed feature
A base-Tag convenience method returning percentile values of the resolved series,
toolbox-free, inherited by every subclass:
p95 =tag.percentile(95); % scalar level -> scalar value
pv =tag.percentile([55095]); % vector levels -> vector of values
pv =tag.percentile([595], t0, t1); % over a time window (mirrors getStats #223 range args)
m =tag.median(); % optional convenience == percentile(50)
r =tag.iqr(); % optional convenience == percentile(75) - percentile(25)
Rough sketch
Single method on libs/SensorThreshold/Tag.m (base class — same placement as getStats #223 and the rest of the family), built on the existing accessors getXY (Tag.m:120) / getXYRange(obj, tStart, tEnd) (Tag.m:125, which already returns the full series for
empty bounds):
Drop NaNs; guard the empty series; validate levels are in [0, 100].
Ys = sort(Y(:)); then the standard linear-interpolation percentile: i = p/100 * (n-1) + 1, interpolate between Ys(floor(i)) and Ys(ceil(i)).
Return values matching the shape of the requested levels.
Pure-function, read-only: no new property, notoStruct/fromStruct change, no
Tag/DashboardWidget contract touched. Output is a plain numeric array — same downstream shape
as the rest of the family.
Value
Medium-High. Completes the Tag statistics surface with the robust / order-statistic
dimension that #223 deliberately left out and that #251 shows is wanted; unlocks
exceedance-level, median, and IQR workflows the library currently forces users to leave for.
Constraints check
Toolbox-free:⚠️important — prctile and quantile are Statistics Toolbox
functions and must not be used. The sort + linear-interpolation implementation is base
MATLAB and Octave, keeping the method toolbox-free.
Backward-compatible: a brand-new method cannot break existing scripts or serialized
dashboards; no serialization or contract change.
Pure MATLAB/Octave: yes (sort + arithmetic only).
Works through the existing Tag contract: yes — reuses getXY / getXYRange.
Effort estimate
S — one method (+ optional median / iqr one-liners) in a single file, plus a focused
test (known vector → known percentiles at endpoints and interior; scalar-vs-vector level
input; NaN handling; empty-series guard; time-range path).
Problem / motivation
The
Taganalysis family has grown a rich set of reduction primitives, but itsstatistics surface only covers moment statistics. #223 (
getStats) was scopedexplicitly to
N / Min / Max / Mean / Rms / Std— the summing/squaring family — anddeliberately left out order statistics (median, percentiles, IQR). Meanwhile #251
(
HistogramWidget: overlay distribution percentiles) shows the domain actively wantspercentiles, but it renders them as a widget display overlay — there is no way to get
percentile values from a
Tagprogrammatically.Verified gap:
grep -rniE "percentile|quantile|prctile" libs/SensorThreshold/→ nothing.Order statistics answer questions moment statistics cannot:
mean(Tag: add a public getStats() statistics primitive (N/Min/Max/Mean/Rms/Std over a series or time range) #223) misleads.These are canonical sensor-analysis / loads / duty-cycle descriptors. Today an engineer must
drop to
getXYand hand-roll a sort every time.Proposed feature
A base-
Tagconvenience method returning percentile values of the resolved series,toolbox-free, inherited by every subclass:
Rough sketch
Single method on
libs/SensorThreshold/Tag.m(base class — same placement asgetStats#223 and the rest of the family), built on the existing accessors
getXY(Tag.m:120) /getXYRange(obj, tStart, tEnd)(Tag.m:125, which already returns the full series forempty bounds):
[~, Y] = obj.getXYRange(tStart, tEnd)(orgetXYwhen no range) — reuse the samerange plumbing Tag: add a public getStats() statistics primitive (N/Min/Max/Mean/Rms/Std over a series or time range) #223 uses.
[0, 100].Ys = sort(Y(:));then the standard linear-interpolation percentile:i = p/100 * (n-1) + 1, interpolate betweenYs(floor(i))andYs(ceil(i)).Pure-function, read-only: no new property, no
toStruct/fromStructchange, noTag/DashboardWidget contract touched. Output is a plain numeric array — same downstream shape
as the rest of the family.
Value
Medium-High. Completes the Tag statistics surface with the robust / order-statistic
dimension that #223 deliberately left out and that #251 shows is wanted; unlocks
exceedance-level, median, and IQR workflows the library currently forces users to leave for.
Constraints check
prctileandquantileare Statistics Toolboxfunctions and must not be used. The sort + linear-interpolation implementation is base
MATLAB and Octave, keeping the method toolbox-free.
dashboards; no serialization or contract change.
sort+ arithmetic only).Tagcontract: yes — reusesgetXY/getXYRange.Effort estimate
S — one method (+ optional
median/iqrone-liners) in a single file, plus a focusedtest (known vector → known percentiles at endpoints and interior; scalar-vs-vector level
input; NaN handling; empty-series guard; time-range path).
Dedup / relationship note (honest triage flag)
getStats) is the moment family and explicitly excludes percentiles — thisis the order-statistics sibling.
getStatsto emitpercentiles) rather than add a separate method — both are toolbox-free and additive. This
is a product decision.
AI-proposed via /feature-scout — needs a human product decision before implementation.