#!/usr/bin/env dvo

# XXX need alternate source for camID (if !cam) and warpID (if !warp)

# .ippcheckrc defines smf.compare books, dvo databases, and other references
input $HOME/.ippcheckrc

module truth.pro
module cammask.pro
module camstats.pro
module warpmask.pro
module warpstats.pro
module diffmask.pro
module smfcheck.pro

#####
macro check.exposure.dvo
  local SKIP_PLOTS CAMERA

  $CAMERA = gpc1  

  # strip out optional arguments
  getargs -no-cam   BOOL  -var SKIP_CAM
  getargs -no-warp  BOOL  -var SKIP_WARP
  getargs -no-diff  BOOL  -var SKIP_DIFF
  getargs -no-plots BOOL  -var SKIP_PLOTS
  getargs -camera   VALUE -var CAMERA

  if ($0 != 3)
    echo "USAGE: check.exposure.dvo (expname) (dgroup)"
    echo " -no-cam, -no-warp, -no-diff, -no-plots"
    echo " [-camera gpc2]"
    break
  end

  local expname camdgrp
  $expname = $1
  $camdgrp = $2
 
  $OUTVERSION = DVO; # used to define output names
  $REFMODE = DVO;    # used by plot.exposure.user for input

  make.truth.sources $CAMERA $expname $PV3_CATDIR DVO
  if (not($SKIP_CAM))  get.camera.eff $CAMERA $expname $camdgrp $REFSOURCE
  if (not($SKIP_WARP)) get.warp.eff   $CAMERA $expname $camID   $REFSOURCE
  if (not($SKIP_DIFF)) get.diff.eff   $CAMERA $expname $warpID  $REFSOURCE

  if (not($SKIP_PLOTS)) plot.exposure.real $expname
end

#####
macro check.exposure.mpc
  local SKIP_PLOTS CAMERA

  $CAMERA = gpc1  

  # strip out optional arguments
  getargs -no-cam   BOOL  -var SKIP_CAM
  getargs -no-warp  BOOL  -var SKIP_WARP
  getargs -no-diff  BOOL  -var SKIP_DIFF
  getargs -do-plots BOOL  -var DO_PLOTS;   
  getargs -use-refs BOOL  -var USE_REFSOURCE
  getargs -camera   VALUE -var CAMERA;

  if ($0 != 4)
    echo "USAGE: check.exposure.mpc (expname) (dgroup) (mpcfile)"
    break
  end

  local expname camdgrp mpcfile
  $expname = $1
  $camdgrp = $2
  $mpcfile = $3
 
  # use a larger match radius for the asteroids
  # MATCH_RADIUS is in pixels 
  $MATCH_RADIUS = 8.0; # XXX add option to set the radius?
  $OUTVERSION = MPC
  $COPYMASKS = 0

  make.truth.sources $CAMERA $expname $mpcfile MPC; # sets the value of REFSOURCE 

  if (not($SKIP_CAM)) get.camera.eff     $CAMERA $expname $camdgrp $REFSOURCE

  # CAMSOURCE lists all REFSOURCE entries which actually fall on a chip, while REFSOURCE includes
  # the objects which are in the larger field.  The latter is not accurate for the detection fraction
  # but, if we did not measure the camera sources, we must use REFSOURCE

  if ($USE_REFSOURCE || $SKIP_CAM)
    if (not($SKIP_WARP)) get.warp.eff    $CAMERA $expname $camID    $REFSOURCE
    if (not($SKIP_DIFF)) get.diff.eff    $CAMERA $expname $warpID   $REFSOURCE
  else
    # load data from cam stage output:
    $USE_CAMSOURCE = 1; # this is used by get.warp.eff to choose the correct fields
    if (not($SKIP_WARP)) get.warp.eff    $CAMERA $expname $camID    $CAMSOURCE
    if (not($SKIP_DIFF)) get.diff.eff    $CAMERA $expname $warpID   $CAMSOURCE
  end

  if ($DO_PLOTS) plot.exposure.real $expname
end

# XXX uses fixed name for orbit file (MPCORB.DAT)
macro make.mpc.refsources
  local GET_ORBITS

  # strip out optional arguments
  getargs -get-orbits BOOL -var GET_ORBITS

  if ($0 != 7)
    echo "USAGE: make.mpc.refsources (Tmin) (Tmax) (Rmin) (Rmax) (Dmin) (Dmax) [-get-orbits]"
    break
  end

  local Tmin Tmax Rmin Rmax Dmin Dmax
  $Tmin = $1
  $Tmax = $2
  $Rmin = $3
  $Rmax = $4
  $Dmin = $5
  $Dmax = $6

  if ($GET_ORBITS)
    # download the most current MPCORB.DAT file with:
    exec rm -f MPCORB.DAT
    exec wget https://www.minorplanetcenter.net/iau/MPCORB/MPCORB.DAT
  end

  $Tref = int($Tmin)
  exec mpcorb_predict trange MPCORB.DAT $Tmin $Tmax $Rmin $Rmax $Dmin $Dmax mpcorb.trange.$Tref.fits
end

#####
macro plot.exposure.user
  $REFMODE = DVO

  # strip out optional arguments
  getargs -no-cam   BOOL  -var SKIP_CAM
  getargs -no-warp  BOOL  -var SKIP_WARP
  getargs -no-diff  BOOL  -var SKIP_DIFF
  getargs -refmode  VALUE -var REFMODE

  if ($0 != 2)
    echo "USAGE: plot.exposure.user (expname)"
    echo " -no-cam, -no-warp, -no-diff"
    echo " -refmode MODE : MODE = MPC, DVO"
    break
  end

  local expname; $expname = $1
  plot.exposure.real $expname
end

##### plot.exposure.user strips optional arguments and calls plot.exposure.real
macro plot.exposure.real
  if ($0 != 2)
    echo "USAGE: plot.exposure.real (expname)"
    break
  end
  local expname; $expname = $1

  $KAPA = kapa -noX; # XXX make this optional (default: do not display)
  antialias 0.5

  if (not($SKIP_CAM))
    load.camstats  $expname.stats/$expname.$REFMODE.cam.stf
    plot.camstats.fracs;  png -name $expname.stats/$expname.$REFMODE.camfracs.png
    plot.camstats.resid;  png -name $expname.stats/$expname.$REFMODE.camresid.png
  end
  
  if (not($SKIP_WARP))
    load.warpstats $expname.stats/$expname.$REFMODE.wrp.stf
    plot.warpstats.fracs; png -name  $expname.stats/$expname.$REFMODE.wrpfracs.png
  end

  if (not($SKIP_DIFF))
    load.camstats  $expname.stats/$expname.$REFMODE.dif.stf
    plot.camstats.fracs;  png -name  $expname.stats/$expname.$REFMODE.diffracs.png
    plot.camstats.resid;  png -name  $expname.stats/$expname.$REFMODE.difresid.png
  end
end

##### plot.exposure.glob
macro plot.exposure.glob
  $REFMODE = DVO

  # strip out optional arguments
  getargs -no-cam   BOOL  -var SKIP_CAM
  getargs -no-warp  BOOL  -var SKIP_WARP
  getargs -no-diff  BOOL  -var SKIP_DIFF
  getargs -refmode  VALUE -var REFMODE

  if ($0 != 3)
    echo "USAGE: plot.exposure.glob (expglob) (outroot)"
    echo " -no-cam, -no-warp, -no-diff"
    echo " -refmode MODE : MODE = MPC, DVO"
    break
  end

  local expglob outroot
  $expglob = $1
  $outroot = $2

  dirname $outroot -var outdir; mkdir $outdir

  $KAPA = kapa -noX; # XXX make this optional (default: do not display)
  antialias 0.5

  if (not($SKIP_CAM))
    load.camstats  $expglob.$REFMODE.cam.stf
    plot.camstats.fracs;  png -name $outroot.$REFMODE.camfracs.png
    plot.camstats.resid;  png -name $outroot.$REFMODE.camresid.png
  end
  
  if (not($SKIP_WARP))
    load.warpstats $expglob.$REFMODE.wrp.stf
    plot.warpstats.fracs; png -name  $outroot.$REFMODE.wrpfracs.png
  end

  if (not($SKIP_DIFF))
    load.camstats  $expglob.$REFMODE.dif.stf
    plot.camstats.fracs;  png -name  $outroot.$REFMODE.diffracs.png
    plot.camstats.resid;  png -name  $outroot.$REFMODE.difresid.png
  end
end

# The ippCheck class specifies the group of validation table to use for the analysis.
# When comparing a specific processing, planned or expected deviations from previous 
# results can be encoded uniquely in the class
macro init.class

  if (not($?IPPCHECK_CLASS))
    $IPPCHECK_CLASS = default
  end

  # look for command-line argument of the form -class ()
  local i

# for i 0 $argv:n
# NOTE: the opihi for-loop construct evaluates the loop conditions
# only once before the loop starts.  Changing the value of argv:n
# during the loop will cause problems in that context.  Also, we 
# need to avoid incrementing $i when we strip off arguments

# the opihi 'while' loop correctly reevaluates the condition on each loop

  $i = 0
  while ($i < $argv:n)
    if ("$argv:$i" == "-class")
      if ($argv:n < $i + 2)
        echo "ERROR: incorrect usage: -class is missing classname: -class (classname)"
        break
      end
      list argv -del -class
      $IPPCHECK_CLASS = $argv:$i
      list argv -del $IPPCHECK_CLASS
    else
      $i ++
    end
  end

  # class-specific macros to define the class tables 
  # should be listed in ~/.ippcheckrc 
  ippcheck.class.$IPPCHECK_CLASS
end

macro init.stage
  if ($0 < 2) 
    echo "USAGE: init.stage (stage)"
    break
  end

  if (("$1" == "cam") || ("$1" == "camera")) init.camera
  if (("$1" == "wrp") || ("$1" == "warp"))   init.warp
  if (("$1" == "dif") || ("$1" == "diff"))   init.diff
  
  if (not($?PSF_FIELDS))
    echo "ERROR : invalid stage $1 or PSF_FIELDS not defined"
    break
  end
  if (not($?PSF_KEYS))
    echo "ERROR : PSF_KEYS not defined"
    break
  end
  if (not($?HDR_KEYS))
    echo "ERROR : HDR_KEYS not defined"
    break
  end

  # Load PASS/FAIL criteria definitions
  smf.compare.parse.book $PSF_FIELDS  psfFields
  smf.compare.parse.book $PSF_KEYS    psfKeys
  smf.compare.parse.book $HDR_KEYS    hdrKeys

  # determine the number of tests per chip and cmf/smf file
  local Nfields
  book npages psfFields -var Nfields
  $NTESTS_CHIP = $Nfields + 4
  $NTESTS_CMF  = $NTESTS_CHIP * $NCHIPS + 2
end

macro show.usage
  echo "USAGE: ippCheck (mode) ..."
  echo "   EG: ippCheck mpc  (expname) (dgroup) [mpcfile]"
  echo "   EG: ippCheck dvo  (expname) (dgroup)"
  echo "   EG: ippCheck smf (stage) (outroot) (smf1) (smf2) [+plot]"
  echo "   EG: ippCheck cmf (stage) (outroot) (smf1) (smf2) [+plot]"
  echo "   EG: ippCheck smf.dgrp.exp (stage) (outroot) (expname) (dgroup1) (dgroup2) [+plot]"
  echo "   EG: ippCheck smf.dgrp.all (stage) (outroot) (dgroup1) (dgroup2) [+plot]"
  echo "   EG: ippCheck plot (expname)"
  echo "   EG: ippCheck plot.glob (expglob) (outroot)"
  echo "   EG: ippCheck mpcrefs (Tmin) (Tmax) (Rmin) (Rmax) (Dmin) (Dmax)"

  echo " also equivalent:"
  echo "   EG: ippCheck smf.compare.exp.by.datagroup (stage) (outroot) (expname) (dgroup1) (dgroup2) [+plot]"
  echo "   EG: ippCheck smf.compare.all.by.datagroup (stage) (outroot) (dgroup1) (dgroup2) [+plot]"
end

if ($SCRIPT)
  if ($argv:n < 1)
    show.usage
    break
  end

  # loads the requested class (finds and removes -class CLASSNAME) argument
  init.class

  # arguments to the script are given as $argv:0 - $argv:n
  # argument lists are passed to macros called below with $arglist
  list argv -join arglist -start 1

  if ("$argv:0" == "dvo")
    check.exposure.dvo $arglist
    exit 0
  end

  if ("$argv:0" == "mpc")
    check.exposure.mpc $arglist
    exit 0
  end

  if ("$argv:0" == "mpcrefs")
    make.mpc.refsources $arglist
    exit 0
  end

  # compare output products for a single exposure
  if (("$argv:0" == "smf") || ("$argv:0" == "cmf"))
    if ($argv:n < 2) 
      echo "USAGE: ippCheck smf (stage) (outroot) (smf1) (smf2) [+plot]"
      echo "USAGE: ippCheck cmf (stage) (outroot) (smf1) (smf2) [+plot]"
      echo "   EG: ippCheck smf camera  (cctest) neb:///gpc1/ipc/o6370g0351o.2133651.smf neb:///gpc1/ipc/o6370g0351o.2497362.smf [+plot]"
      echo "   EG: ippCheck cmf warp    (wwtest) neb:///gpc1/ipc/o6370g0351o.wrp.2109044.skycell.1278.000.cmf neb:///gpc1/ipc/o6370g0351o.wrp.2465875.skycell.1278.000.cmf [+plot]"
      exit 2
    end

    init.stage $argv:1
    list argv -join arglist -start 2

    # If we run on a single file, define the TAP test plan here.  The
    # value of NTESTS_CHIP is set by the init.stage call based on psfFields
    # The number of chips depends on the camera and stage
    # For warps and diffs, the number of chips is 1 since a single cmf holds a single table
    # there are 2 tests at the end of smf.compare.all.extensions
    tap.plan $NTESTS_CMF
    smf.compare.all.extensions $arglist
    tap.done

    exit 0
  end

  # compare output products for a single exposure by data_groups
  if (("$argv:0" == "smf.compare.exp.by.datagroups") || ("$argv:0" == "smf.dgrp.exp"))
    if ($argv:n < 2) 
      echo "USAGE: ippCheck smf.dgrp.exp (stage) (outroot) (expname) (dgroup1) (dgroup2) [+plot]"
      echo "   EG: ippCheck smf.dgrp.exp camera  (cctest) o6370g0351o MOPS.dailytestset.20190516ops40745  eamtest.20220208"
      echo "   EG: ippCheck smf.dgrp.exp warp    (wwtest) o6370g0351o MOPS.dailytestset.20190516ops40745  eamtest.20220208"
    end

    init.stage $argv:1
    list argv -join arglist -start 2

    if (("$argv:1" == "cam") || ("$argv:1" == "camera"))
      smf.compare.cam.exp.by.datagroups $arglist
      exit 0
    end
    if (("$argv:1" == "wrp") || ("$argv:1" == "warp"))
      smf.compare.wrp.exp.by.datagroups $arglist
      exit 0
    end
    if (("$argv:1" == "dif") || ("$argv:1" == "diff"))
      smf.compare.dif.exp.by.datagroups $arglist
      exit 0
    end
  end

  # compare all exposures for a pair of data_groups
  if (("$argv:0" == "smf.compare.all.by.datagroups") || ("$argv:0" == "smf.dgrp.all"))
    if ($argv:n < 2) 
      echo "USAGE: ippCheck smf.dgrp.all (stage) (outroot) (dgroup1) (dgroup2) [+plot]"
      echo "   EG: ippCheck smf.dgrp.all camera  (cctest) MOPS.dailytestset.20190516ops40745  eamtest.20220208"
      echo "   EG: ippCheck smf.dgrp.all warp    (wwtest) MOPS.dailytestset.20190516ops40745  eamtest.20220208"
    end

    init.stage $argv:1
    list argv -join arglist -start 2

    if (("$argv:1" == "cam") || ("$argv:1" == "camera"))
      smf.compare.cam.all.by.datagroups $arglist
      exit 0
    end
    if (("$argv:1" == "wrp") || ("$argv:1" == "warp"))
      smf.compare.wrp.all.by.datagroups $arglist
      exit 0
    end
    if (("$argv:1" == "dif") || ("$argv:1" == "diff"))
      smf.compare.dif.all.by.datagroups $arglist
      exit 0
    end
  end

  if ("$argv:0" == "plot")
    plot.exposure.user $arglist
    exit 0
  end

  if ("$argv:0" == "plot.glob")
    plot.exposure.glob $arglist
    exit 0
  end

  show.usage
  exit 2
end

