!******************************************************************************!
! This tests the functionality of normalize.
!
! @author  Scott Fernandez, Neon Ngo
! @since   NeXtMidas 3.1.0
!******************************************************************************!
startmacro s:func[""]
  switch INTERACTIVE interAct GET DEF=FALSE  SDEF=TRUE  ! for normal interactive test(s)
  switch KEEP        keep   GET DEF=interAct SDEF=TRUE  ! to keep generated / output files

  res prefix "test_normalize_"

  if func NEQS "" and func NEQS "ALL" then
    call test_^{func}
    stop
  endif

  call test_basic_real    "^{prefix}c1.tmp" "^{prefix}z1.tmp" "SF"
  call test_basic_real    "^{prefix}c2.tmp" "^{prefix}z2.tmp" "SD"
  call test_basic_complex "^{prefix}c3.tmp" "^{prefix}z3.tmp" "CF"
  call test_basic_complex "^{prefix}c4.tmp" "^{prefix}z4.tmp" "CD"

  call test_advanced_real    "^{prefix}in1.tmp" "^{prefix}out1.tmp" "SF"
  call test_advanced_real    "^{prefix}in2.tmp" "^{prefix}out2.tmp" "SD"
  call test_advanced_complex "^{prefix}in3.tmp" "^{prefix}out3.tmp" "CF"
  call test_advanced_complex "^{prefix}in4.tmp" "^{prefix}out4.tmp" "CD"

  call test_type2000

  ! Clean up remaining test files
  if keep ISFALSE then files/e ^{prefix}*

  %test_normalize_pipe/interactive=^interAct
endmacro

!******************************************************************************!
! 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

!******************************************************************************!
! Process unhandled exceptions
procedure processException m:emsg
  assert/text="^reg.main.name: Unexpected exception: ^{emsg} DATA=^{emsg.data}" false
return

!******************************************************************************!
! Basic tests for real data
procedure test_basic_real S:INFILE[c1] S:OUTFILE[z1] S:FORMAT[SF]
  call test_basic_common INFILE OUTFILE FORMAT

  normalize INFILE OUTFILE mode=PEAK
  maxmin/quiet OUTFILE temp_max1 temp_min1
  assert/text="^reg.main.name: ^{FORMAT}, mode=PEAK: basic behavior is correct" temp_max1 eq 0 and temp_min1 eq 0

  erase INFILE OUTFILE
return

!******************************************************************************!
! Basic tests for complex data
procedure test_basic_complex S:INFILE[c1] S:OUTFILE[z1] S:FORMAT[CF]
  call test_basic_common INFILE OUTFILE FORMAT

  erase INFILE OUTFILE
return

!******************************************************************************!
! Basic tests common to complex and real data
procedure test_basic_common S:INFILE[c1] S:OUTFILE[z1] S:FORMAT[SF]
  WAVEFORM INFILE FORMAT ELEM=1k SHAPE=CONSTANT AMP=7

  normalize INFILE OUTFILE mode=MEAN
  maxmin/quiet OUTFILE temp_max1 temp_min1
  assert/text="^reg.main.name: ^{FORMAT}, mode=MEAN: max (^temp_max1) and min (^temp_min1) of normalized constant are 0" temp_max1 eq 0 and temp_min1 eq 0

  normalize INFILE OUTFILE mode=SD
  maxmin/quiet OUTFILE temp_max1 temp_min1
  assert/text="^reg.main.name: ^{FORMAT}, mode=SD:   max and min of normalized constant are 0" temp_max1 eq 0 and temp_min1 eq 0

  normalize INFILE OUTFILE mode=NONE shift=-7
  maxmin/quiet OUTFILE temp_max1 temp_min1
  assert/text="^reg.main.name: ^{FORMAT}, mode=NONE: max and min are 0 with -7 SHIFT" temp_max1 eq 0 and temp_min1 eq 0
return

!******************************************************************************!
! Advanced tests for real data
procedure test_advanced_real S:INFILE[temp_in] S:OUTFILE[temp_out] S:FORMAT[SF]
  ! error tolerance found through multiple test runs
  set error_tol 1E-6
  call test_advanced_common INFILE OUTFILE FORMAT

  normalize INFILE OUTFILE mode=PEAK
  STATISTICS IN=OUTFILE MAX=temp_max MIN=temp_min
  assert/text="^reg.main.name: ^FORMAT data: Comparing output to known values" temp_min eq -0.5 and temp_max eq 0.5

  if keep isFalse then
    if /debug then say "cleaning up generated test files..."
    erase temp_white temp_cons INFILE OUTFILE
  endif
return

!******************************************************************************!
! Advanced tests for complex data
procedure test_advanced_complex S:INFILE[temp_in] S:OUTFILE[temp_out] S:FORMAT[SF]
  ! error tolerance found through multiple test runs
  set error_tol 1E-3
  call test_advanced_common INFILE OUTFILE FORMAT

  erase temp_white temp_cons INFILE OUTFILE
return

!******************************************************************************!
! Advanced tests common to complex and real data
procedure test_advanced_common S:INFILE["temp_in.tmp"] S:OUTFILE["temp_out.tmp"] S:FORMAT["SF"]
  call setup_advanced_files INFILE FORMAT

  normalize INFILE OUTFILE mode=MEAN
  STATISTICS IN=OUTFILE MEAN=temp_mean
  CALC temp_mean temp_mean ABS
  assert/text="^reg.main.name: Advanced ^{FORMAT}, mode=MEAN: Mean is close to zero: ^temp_mean" temp_mean < error_tol

  normalize INFILE OUTFILE mode=SD
  STATISTICS IN=OUTFILE MEAN=temp_mean SDEV=temp_sdev
  CALC temp_mean temp_mean ABS
  CALC temp_sdev temp_sdev 1 - ABS
  assert/text="^reg.main.name: Advanced ^{FORMAT}, mode=SD:   Mean is close to zero: ^temp_mean" temp_mean < error_tol
  assert/text="^reg.main.name: Advanced ^{FORMAT}, mode=SD:   sdev-1 is close to zero: ^temp_sdev" temp_sdev < error_tol

  normalize temp_white OUTFILE mode=NONE shift=randShift
  COMPARE INFILE OUTFILE MAX_OUT=temp_max MIN_OUT=temp_min
  assert/text="^reg.main.name: Advanced ^{FORMAT}, mode=NONE: Shifting works " temp_max eq 0 and temp_min eq 0

  if /debug then
    say ^INFILE
    say ^OUTFILE
  endif
return

!******************************************************************************!
! Advanced tests
procedure setup_advanced_files S:INFILE[temp_out] S:FORMAT[SF]
  CALCULATOR randLength RANDOM 10k * FLOOR 4k +
  CALCULATOR randAmp1   RANDOM 53 * FLOOR 1 +
  CALCULATOR randShift   RANDOM 32 * FLOOR 1 +
  WAVEFORM OUT=temp_white FORMAT ELEM=randLength SHAPE=WHITE    AMP=randAmp1
  WAVEFORM OUT=temp_cons  FORMAT ELEM=randLength SHAPE=CONSTANT AMP=randShift
  FCALC INFILE temp_white temp_cons +
return

!******************************************************************************!
! test normalizing a Type 2000 file (common)
procedure test_type2000_common FN:infile FN:outfile S:mode D:expMean D:expSDev D:expMin D:expMax
  normalize infile outfile mode=mode
  statistics outfile table=stats

  assert/text="^reg.main.name: Type 2000, mode=^{mode}, mean of output" stats.mean eqt expMean
  assert/text="^reg.main.name: Type 2000, mode=^{mode}, sdev of output" stats.sdev eqt expSDev
  assert/text="^reg.main.name: Type 2000, mode=^{mode}, min of output"  stats.min  eqt expMin
  assert/text="^reg.main.name: Type 2000, mode=^{mode}, max of output"  stats.max  eqt expMax

  if keep isFalse then
    erase outfile
  endif
return

!******************************************************************************!
! test normalizing a Type 2000 file
procedure test_type2000
  set t2000file "nxm.sys.dat.apenny.prm"
  set keep interAct ! interactive requires output files to be kept around to be plotted
  call test_type2000_common t2000file ram:norm2000_sdev "SD"   -3.716245E-10 0.999999999   -3.985391616 2.485055208
  call test_type2000_common t2000file ram:norm2000_mean "MEAN"  0.0         59.470454197 -164.34375   169.328125
  call test_type2000_common t2000file ram:norm2000_peak "PEAK" -0.048390249  0.299253265    -0.5        0.5

  if interAct then
    set instructions "The PLOTs of the various normalized modes on the left column should look like the ones on the right"
    pipe on
      panel/msgid=MAIN/setup/controls=gc
      gcontrol label macro "Test MACRO"
      gcontrol menu  main "Exit with Status =" "PASS,FAIL" TABLE={ItemColors={PASS="GREEN",FAIL="RED"}} /tleft
      gcontrol text  idtext "Instructions" instructions 24 8 /title

      plot/id=sdevplot ram:norm2000_sdev
      plot/id=meanplot ram:norm2000_mean
      plot/id=peakplot ram:norm2000_peak

      plot/id=expsdevplot nxm.dsp.test.apenny_norm_sd.prm
      plot/id=expmeanplot nxm.dsp.test.apenny_norm_mean.prm
      plot/id=exppeakplot nxm.dsp.test.apenny_norm_peak.prm
    pipe off
  endif

return
