!******************************************************************************!
! Tests for INVFFT command
!
! Arguments: None
!
!
! @bug      2495, others...
! @author:  JC4 / J Bauer / J Hallam 
! @version: $Id: test_invfft.mm,v 1.6 2013/04/30 17:30:32 ams Exp $
!******************************************************************************!

startmacro
  res i:expectedresult 1
  say "Running INVFFT Tests, NO WINDOW"
  call runtests NONE expectedresult
  say "Running INVFFT Tests, HAMM WINDOW"
  call runtests HAMM expectedresult 
  ! Even hanning window is not undoable, it has a zero.
  ! The tests should run, but fail
  !say "The following tests should fail - asymmetrical hanning window is not undoable because of the zero."
  set expectedresult 0
  say "Running INVFFT Tests, HANN WINDOW"
  call runtests HANN expectedresult
  

endmacro

procedure runtests s:wintype i:expectedresult
  result eflag 0

  set wavefile    "test_invfft_wav1"
  set wavefile2   "test_invfft_wav2"
  set fftfile1    "test_invfft_spec1"
  set fftfile2    "test_invfft_spec2"
  set invfftfile1 "test_invfft_out1"
  set invfftfile2 "test_invfft_out2"
  set waveshape    "WHITE"

  ! Test FFT options
  call test_complex_input "^wavefile" "^fftfile1" "^fftfile2" "^invfftfile1" "^invfftfile2" "^waveshape" "^wintype" expectedresult
  call test_complex_input_multi "^wavefile" "^fftfile1" "^fftfile2" "^invfftfile1" "^invfftfile2" "^waveshape" "^wintype" expectedresult
  call test_complex_input_overlap "^wavefile" "^fftfile1" "^fftfile2" "^invfftfile1" "^invfftfile2"  "^waveshape" "^wintype" expectedresult
  call test_real_input "^wavefile" "^fftfile1" "^fftfile2" "^invfftfile1" "^invfftfile2" "^waveshape" "^wintype" expectedresult

  ! Cleanup test files
  files/e test_invfft*

return

!******************************************************************************!
! Main process message for this macro. Should be right after the ENDMACRO.
procedure processMessage m:msg
  if msg.name eqs "MAIN" then
    assert/text="^reg.main.name: User indicated tests" msg.data eqss "PASS"
    pipe stop
  else
    !say "Unhandled message name: ^msg.name from fid: ^msg.fid data: ^msg.data"
  endif
return

!******************************************************************************!
!  Basic tests for FFT
!
procedure test_complex_input fn:input fn:output1 fn:output2 fn:invoutput1 fn:invoutput2 s:shape s:windowtype i:expectedresult
  res NFFT 1k
  res FREQ 2
  res FS NFFT
  calc TS 1 FS /
  res MAX_THR 1.0e-5
  res MIN_THR -1.0e-5
  WAVEFORM,OUT=^input,FORM=CF,ELEM=^NFFT,SHAPE=^SHAPE,AMP=1,FREQ=^FREQ,PHASE=0,START=0,DELTA=^TS

  FFT/1D,IN1=^input,OUT1=^output1,NFFT=^NFFT,WIN=^windowtype,OVER=0,NAVG=1 
  FFT/1D/ROTATE=F,IN1=^input,OUT1=^output2,NFFT=^NFFT,WIN=^windowtype,OVER=0,NAVG=1
  
  INVFFT/1D,IN=^output1,OUT=^invoutput1,NFFT=^NFFT,WIN=^windowtype
  INVFFT/1D/ROTATE=F,IN=^output2,OUT=^invoutput2,NFFT=^NFFT, WIN=^windowtype

  compare, IN1=^input, IN2=^invoutput1, MAX_OUT=max, MIN_OUT=min, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR
  assert/text="^reg.main.name ^windowtype (complex): FFT/1D (ROTATE ON) " compresult EQ expectedResult
  
  compare, IN1=^input, IN2=^invoutput2, MAX_OUT=max, MIN_OUT=min, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR
  assert/text="^reg.main.name ^windowtype (complex): FFT/1D/ROTATE=F " compresult EQ expectedResult
 

  status ^input ystart=ysi ydelta=ydi, xstart=xsi, xdelta=xdi 
  status ^invoutput1 ystart=yso ydelta=ydo, xstart=xso, xdelta=xdo
  !assert/text="^reg.main.name XSTART: ^xsi ^xso" xsi EQ xso 
  !assert/text="^reg.main.name XDELTA: ^xdi ^xdo" xdi EQ xdo 
  
  FFT,IN1=^input,OUT1=^output1,NFFT=^NFFT,WIN=^windowtype,OVER=0,NAVG=1 
  FFT/ROTATE=F,IN1=^input,OUT1=^output2,NFFT=^NFFT,WIN=^windowtype,OVER=0,NAVG=1
  
  INVFFT,IN=^output1,OUT=^invoutput1,NFFT=^NFFT, WIN=^windowtype
  INVFFT/ROTATE=F,IN=^output2,OUT=^invoutput2,NFFT=^NFFT, WIN=^windowtype

  compare, IN1=^input, IN2=^invoutput1, MAX_OUT=max, MIN_OUT=min, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR
  assert/text="^reg.main.name ^windowtype (complex): FFT (ROTATE ON) " compresult EQ expectedresult
  
  compare, IN1=^input, IN2=^invoutput2, MAX_OUT=max, MIN_OUT=min, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR
  assert/text="^reg.main.name ^windowtype (complex): FFT/ROTATE=F " compresult EQ expectedresult
 

return

!  Test complex input NFFT < NSAMPS
procedure test_complex_input_multi fn:input fn:output1 fn:output2 fn:invoutput1 fn:invoutput2 s:shape s:windowtype i:expectedresult
  res NSAMPS 8k
  res NFFT 1k
  res FREQ 2
  res FS NFFT
  calc TS 1 FS /
  res MAX_THR 1.0e-5
  res MIN_THR -1.0e-5
  WAVEFORM,OUT=^input,FORM=CF,ELEM=^NSAMPS,SHAPE=^SHAPE,AMP=1,FREQ=^FREQ,PHASE=0,START=0,DELTA=^TS

  FFT,IN1=^input,OUT1=^output1,NFFT=^NFFT,WIN=^windowtype,OVER=0,NAVG=1 
  FFT/ROTATE=F,IN1=^input,OUT1=^output2,NFFT=^NFFT,WIN=^windowtype,OVER=0,NAVG=1
  
  INVFFT,IN=^output1,OUT=^invoutput1,NFFT=^NFFT, WIN=^windowtype
  INVFFT/ROTATE=F,IN=^output2,OUT=^invoutput2,NFFT=^NFFT, WIN=^windowtype

  !  Appears that the min/max must be dumped into results variables in order to suppress the MIN/MAX INFO statements
  compare, IN1=^input, IN2=^invoutput1, MAX_OUT=max, MIN_OUT=min, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR
  assert/text="^reg.main.name ^windowtype (complex multi): FFT (ROTATE ON) MULTI" compresult EQ expectedresult
  
  compare, IN1=^input, IN2=^invoutput2, MAX_OUT=max, MIN_OUT=min, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR
  assert/text="^reg.main.name ^windowtype (complex multi): FFT/ROTATE=F MULTI" compresult EQ expectedresult

return

!  Test complex input NFFT < NSAMPS with OVERLAP
procedure test_complex_input_overlap fn:input fn:output1 fn:output2 fn:invoutput1 fn:invoutput2 s:shape s:windowtype i:expectedresult
  res OVER 0.37
  res NSAMPS 8k
  res NFFT 1024
  res FREQ 16
  res FS NFFT
  calc TS 1 FS /
  res MAX_THR 1.0e-5
  res MIN_THR -1.0e-5
  WAVEFORM,OUT=^input,FORM=CF,ELEM=^NSAMPS,SHAPE=^SHAPE,AMP=1,FREQ=^FREQ,PHASE=0,START=0,DELTA=^TS

  FFT,IN1=^input,OUT1=^output1,NFFT=^NFFT,WIN=^WINDOWTYPE,OVER=^OVER,NAVG=1 
  FFT/ROTATE=F,IN1=^input,OUT1=^output2,NFFT=^NFFT,WIN=^WINDOWTYPE,OVER=^OVER,NAVG=1
  
  INVFFT,IN=^output1,OUT=^invoutput1,NFFT=^NFFT,OVER=^OVER,WIN=^WINDOWTYPE
  INVFFT/ROTATE=F,IN=^output2,OUT=^invoutput2,NFFT=^NFFT,OVER=^OVER,WIN=^WINDOWTYPE

  !  Appears that the min/max must be dumped into results variables in order to suppress the MIN/MAX INFO statements
  compare, IN1=^input, IN2=^invoutput1, MAX_OUT=max, MIN_OUT=min, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR
  assert/text="^reg.main.name ^windowtype (complex overlap): FFT (ROTATE ON) MULTI" compresult EQ expectedresult
  !say "Complex input overlap diff ^compresult min ^min max ^max" 
  compare IN1=^input, IN2=^invoutput2, MAX_OUT=max, MIN_OUT=min, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR
  !say "Complex input overlap diff ^compresult min ^min max ^max" 
  assert/text="^reg.main.name ^windowtype (complex overlap): FFT/ROTATE=F MULTI" compresult EQ expectedresult
  status ^input ystart=ysi ydelta=ydi, xstart=xsi, xdelta=xdi 
  status ^invoutput1 ystart=yso ydelta=ydo, xstart=xso, xdelta=xdo
  !assert/text="^reg.main.name XSTART: ^xsi ^xso" xsi EQ xso 
  !assert/text="^reg.main.name XDELTA: ^xdi ^xdo" xdi EQ xdo 

return

procedure test_real_input fn:input fn:output1 fn:output2 fn:invoutput1 fn:invoutput2 s:shape s:windowtype i:expectedresult
  res NFFT 8
  res FREQ 2
  res FS NFFT
  calc TS 1 FS /
  res MAX_THR 1.0e-5
  res MIN_THR -1.0e-5
  !say "SHAPE: ^SHAPE"
  WAVEFORM,OUT=^input,FORM=SF,ELEM=^NFFT,SHAPE=^SHAPE,AMP=1,FREQ=^FREQ,PHASE=0,START=0,DELTA=^TS

  !  The default is UNPACK for single frame, so these two tests should be equivalent
  FFT/1D,IN1=^input,OUT1=^output1,NFFT=^NFFT,WIN=^WINDOWTYPE,OVER=0,NAVG=1 
  FFT/1D/PACK=UNPACK,IN1=^input,OUT1=^output2,NFFT=^NFFT,WIN=^WINDOWTYPE,OVER=0,NAVG=1
  
  INVFFT/1D/REAL,IN=^output1,OUT=^invoutput1,NFFT=^NFFT,WIN=^WINDOWTYPE
  INVFFT/1D/REAL/PACK=UNPACK,IN=^output2,OUT=^invoutput2,NFFT=^NFFT,WIN=^WINDOWTYPE
  compare, IN1=^input, IN2=^invoutput1, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR, MAX_OUT=max, MIN_OUT=min
  assert/text="^reg.main.name ^windowtype (real): FFT/1D (DEFAULT) " compresult EQ expectedresult
  
  compare, IN1=^input, IN2=^invoutput2, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR, MAX_OUT=max, MIN_OUT=min
  assert/text="^reg.main.name ^windowtype (real): FFT/1D (UNPACK) " compresult EQ expectedresult
  

  FFT/1D/PACK=DC,IN1=^input,OUT1=^output2,NFFT=^NFFT,WIN=^WINDOWTYPE,OVER=0,NAVG=1
  INVFFT/1D/REAL/PACK=DC,IN=^output2,OUT=^invoutput2,NFFT=^NFFT,WIN=WINDOWTYPE  
  compare, IN1=^input, IN2=^invoutput2, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR, MAX_OUT=max, MIN_OUT=min
  assert/text="^reg.main.name ^windowtype (real): FFT/1D (DC) " compresult EQ expectedresult
 
  !  PACK=ZERO discards the nyquist bin, not possible to recover original data
  ! say "PACK=ZERO discards the nyquist bin, not possible to recover original data.  This should fail." 
  FFT/1D/PACK=ZERO,IN1=^input,OUT1=^output1,NFFT=^NFFT,WIN=^WINDOWTYPE,OVER=0,NAVG=1
  INVFFT/1D/REAL/PACK=ZERO,IN=^output1,OUT=^invoutput1,NFFT=^NFFT,WIN=^WINDOWTYPE
  compare, IN1=^input, IN2=^invoutput1, RESULT=compresult, MAX_THR=^MAX_THR, MIN_THR=^MIN_THR, MAX_OUT=max, MIN_OUT=min
  !  THIS TEST SHOULD FAIL, check for failure
  assert/text="^reg.main.name ^windowtype (real): FFT/1D (ZERO) " compresult NEQ 1
  
  
return

