Skip to content

Commit 2c43c4e

Browse files
timjarskyt-b
authored andcommitted
New MiES algorithmic utility for band pass filtering with Nan, Inf, and rinnging rejection and automatic order reduction
1 parent ceea414 commit 2c43c4e

File tree

1 file changed

+75
-0
lines changed

1 file changed

+75
-0
lines changed

Packages/MIES/MIES_MiesUtilities_Algorithm.ipf

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,3 +595,78 @@ threadsafe Function/WAVE FindIndizes(WAVE numericOrTextWave, [variable col, stri
595595

596596
return result
597597
End
598+
599+
//@brief Band‑pass filters a wave while automatically reducing IIR filter order until the output contains no NaNs/Infs and its SEM is not larger than the original (simple ringing detection).
600+
601+
// -----------------------------------------------------------------------------
602+
// BandPassWithRingingDetection(src, fHigh, fLow, maxOrder)
603+
// -----------------------------------------------------------------------------
604+
// * src – input wave (is **not** modified; a filtered copy called <src>_BPF is produced)
605+
// * fHigh/fLow – pass‑band edge frequencies in Hz (Igor’s band‑pass requires fLow > fHigh; the routine swaps them if needed)
606+
// * maxOrder – starting (maximum) IIR filter order to try (>0)
607+
//
608+
// Logic: iteratively lowers the filter order until three conditions are met:
609+
// 1. FilterIIR executes without error.
610+
// 2. WaveStats reports V_numNaNs = 0 and V_numInfs = 0.
611+
// 3. SEM(filtered) ≤ SEM(original).
612+
//
613+
// Return value: filter order that finally succeeded (0 if every order failed).
614+
// -----------------------------------------------------------------------------
615+
Function bandpass_with_RingingDetection(WAVE src, variable fHigh, variable fLow, variable maxOrder)
616+
617+
// ---- parameter sanity ---------------------------------------------------
618+
ASSERT(maxOrder > 0, "maxOrder must be positive")
619+
if(fLow <= fHigh) // Igor band‑pass expects fLow > fHigh
620+
variable tmp = fLow
621+
fLow = fHigh
622+
fHigh = tmp
623+
endif
624+
625+
// Sampling rate (Hz) – assumes X scaling is in milliseconds
626+
variable samp = 1 / (DeltaX(src) * MILLI_TO_ONE)
627+
628+
// Pre‑compute SEM(original) once
629+
WaveStats/Q src
630+
variable semOrig = V_sem
631+
632+
// Prepare destination wave (same name every call → convenient overwrite)
633+
duplicate/O src, src_BPF
634+
WAVE filtered = src_BPF
635+
636+
variable curOrder = maxOrder, err
637+
do
638+
// -------- copy fresh data into filtered ------------------------------
639+
filtered = src // avoids repeated duplicate/O allocations
640+
641+
// -------- attempt current order --------------------------------------
642+
FilterIIR/LO=(fLow/samp)/HI=(fHigh/samp)/DIM=(ROWS)/ORD=(curOrder) filtered
643+
err = GetRTError(1)
644+
if(err)
645+
Print "FilterIIR failed (order="+num2str(curOrder)+"): "+GetErrMessage(err)
646+
curOrder -= 1
647+
continue
648+
endif
649+
650+
// -------- WaveStats: NaN/Inf + SEM in one call ------------------------
651+
WaveStats/Q filtered
652+
if(V_numNaNs > 0 || V_numInfs > 0)
653+
curOrder -= 1
654+
continue // bad numerical output → lower order
655+
endif
656+
657+
if(V_sem > semOrig) // noisier than original → ringing
658+
curOrder -= 1
659+
continue
660+
endif
661+
662+
// -------- success -----------------------------------------------------
663+
664+
break
665+
while(curOrder > 0)
666+
667+
if(curOrder <= 0)
668+
Print "bandpass_with_RingingDetection(): all orders down to 1 produced NaNs/Infs or increased SEM."
669+
endif
670+
671+
return curOrder
672+
End

0 commit comments

Comments
 (0)