@@ -596,14 +596,14 @@ threadsafe Function/WAVE FindIndizes(WAVE numericOrTextWave, [variable col, stri
596
596
return result
597
597
End
598
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).
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
600
601
601
// -----------------------------------------------------------------------------
602
602
// BandPassWithRingingDetection(src, fHigh, fLow, maxOrder)
603
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)
604
+ // @param src – input wave (is **not** modified; a filtered copy called <src>_BPF is produced)
605
+ // @param fHigh/fLow – pass‑band edge frequencies in Hz (Igor’s band‑pass requires fLow > fHigh; the routine swaps them if needed)
606
+ // @param maxOrder – starting (maximum) IIR filter order to try (>0)
607
607
//
608
608
// Logic: iteratively lowers the filter order until three conditions are met:
609
609
// 1. FilterIIR executes without error.
@@ -612,61 +612,69 @@ End
612
612
//
613
613
// Return value: filter order that finally succeeded (0 if every order failed).
614
614
// -----------------------------------------------------------------------------
615
- Function bandpass_with_RingingDetection ( WAVE src, variable fHigh, variable fLow, variable maxOrder)
615
+ Function [variable curOrder, WAVE filtered] bandpass_with_RingingDetection ( WAVE src, variable fHigh, variable fLow, variable maxOrder)
616
616
617
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
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
+ variable offset = v_avg
632
+
633
+ // Prepare destination wave (same name every call → convenient overwrite)
634
+ duplicate / FREE src, src_BPF
635
+ WAVE /z filtered = src_BPF
636
+
637
+ // remove offset from src copy
638
+ filtered -= offset
639
+
640
+ curOrder = maxOrder
641
+ variable err
642
+ do
643
+ // -------- copy fresh data into filtered ------------------------------
644
+ filtered = src // avoids repeated duplicate/O allocations
645
+
646
+ // -------- attempt current order --------------------------------------
647
+ FilterIIR / LO= ( fLow/ samp) / HI= ( fHigh/ samp) / DIM= ( ROWS) / ORD= ( curOrder) filtered
648
+ err = GetRTError ( 1 )
649
+ if ( err)
650
+ Print "FilterIIR failed (order=" + num2str ( curOrder) + "): " + GetErrMessage ( err)
651
+ curOrder -= 1
652
+ continue
653
+ endif
654
+
655
+ // -------- WaveStats: NaN/Inf + SEM in one call ------------------------
656
+ WaveStats / Q filtered
657
+ if ( V_numNaNs > 0 || V_numInfs > 0 )
658
+ curOrder -= 1
659
+ continue // bad numerical output → lower order
660
+ endif
661
+
662
+ if ( V_sem > semOrig) // noisier than original → ringing
663
+ curOrder -= 1
664
+ continue
665
+ endif
666
+
667
+ // -------- success -----------------------------------------------------
668
+
669
+ break
670
+ while ( curOrder > 0 )
671
+
672
+ if ( curOrder <= 0 )
673
+ Print "bandpass_with_RingingDetection(): all orders down to 1 produced NaNs/Infs or increased SEM."
674
+ endif
675
+
676
+ // add offset back to filtered wave
677
+ filtered += offset
678
+
679
+ return [ curOrder, filtered]
672
680
End
0 commit comments