@@ -595,3 +595,78 @@ threadsafe Function/WAVE FindIndizes(WAVE numericOrTextWave, [variable col, stri
595595
596596 return result
597597End
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