#!/usr/bin/perl
use FileHandle;
use File::Basename;
use Getopt::Long;

$ccw = 7;
$adf_exp = .4;
$adf_win = 32;
$adf_step = 4;
$cc_min = .1;
$cc_max = .9;
$scale = .7;    #display intensity relative scale factor
$exp = .35;	#display intensity exponent
$mli_dir = "";

#command line options parsing, the rest of the arguments are passed to @ARGV
GetOptions ('e=f' => \$exp, 's=f' => \$scale, 'm=s' => \$mli_dir);

if (($#ARGV + 1) < 6){die <<EOS ;}
*** $0
*** Copyright 2013, Gamma Remote Sensing, v2.6 19-Jul-2013 clw ***
*** Adaptive filtering (adf) of a set of differential interferograms ***

usage: $0 <RSLC_tab> <itab> <mli> <diff_dir> [cc_win] [adf_exp] [adf_win] [adf_step] 

    RSLC_tab    (input) two column list of resampled SLC filenames and SLC parameter filenames
             	  1. SLC filename  (includes path)
	          2. SLC parameter filename (includes path)
    itab        (input) table associating interferogram stack records with pairs of RSLC_tab records (text)		
                  1. row number in SLC_tab of the reference SLC 
             	  2. row number in SLC_tab of SLC-2 of the interferogram
             	  3. line number in the itab
                  4. flag used to indicate if this interferogram is used for IPTA processing (0:not used  1:used)
    mli         (input) MLI background image derived from the resampled SLCs with the same dimensions as the interferogram
    diff_dir    differential interferogram directory containing *.diff differential interferogram files    
    cc_win      correlation estimation window range and azimuth size (linear weighting) in pixels, (default: $ccw)
    adf_exp     exponent parameter for adf interferogram filter, (nominal range 0.2-->1.0, default: $adf_exp)
    adf_win     window size for adf filter (default: $adf_win)
    adf_step    range and azimuth filter step size (1 < adf_step <= adf_win/2, default: $adf_step)
    -m mli_dir  (option) use MLI2 as the background image rather than mli image specified on the command line
                mli_dir is the directory containing the mli images
    -s scale    (option) set image display scale factor (default: $scale)   
    -e exp      (option) set image display exponent (default: $exp)
                        
EOS

$rslc_tab  = $ARGV[0];
$itab      = $ARGV[1];
$rmli      = $ARGV[2];
$diff_dir  = $ARGV[3];

if($#ARGV >= 4){
  $ccw = $ARGV[4];
  ($ccw > 2 && $ccw < 63) or die "\nERROR: invalid correlation window size (ccw < 2 || ccw >= 63): $ccw\n";
}

if($#ARGV >= 5){
  $adf_exp = $ARGV[5];
  ($adf_exp > 0.0 && $adf_exp <= 1.0) or die "\nERROR: invalid value for adf filter exponent: $adf_exp\n";
}

if($#ARGV >= 6){
  $adf_win = $ARGV[6];
  ($adf_win >= 0 ) or die "\nERROR: invalid size for adf filter window size: $adf_win\n";
}

$adf_step = $adf_win/8;		#filter step is 1/8 of the window size 

if($#ARGV >= 7){
  $adf_step = $ARGV[7];
  ($adf_step >= 0 && $adf_step <= $adf_win/2) or die "\nERROR: invalid size for adf window step size: $adf_step\n";
}

open(RSLC_TAB, "<$rslc_tab") or die "\nERROR $0: table of resampled SLC images and parameter files does not exist: $rslc_tab\n\n";
print "resampled SLC images and image parameter files: $rslc_tab\n"; 

open(ITAB, "<$itab") or die "\nERROR $0: table of interferometric pairs does not exist: $itab\n\n";
print "table of interferometric pairs: $itab\n"; 

-e $rmli or die "ERROR $0: RMLI reference intensity image file does not exist: $rmli\n";
-d $diff_dir or die "ERROR $0: differential interferogram directory does not exist: $diff_dir\n";
if ($mli_dir ne "") {
  -d $mli_dir or die "ERROR $0: directory containing rmli images does not exist: $mli_dir\n";
}


$log = "$diff_dir/mk_adf_2d.log";  
open(LOG,">$log") or die "ERROR $0: cannot open mk_adf_2d log file: $log\n";
LOG->autoflush;  

$time = localtime;
print "start: $time  log file: $log\n\n";
print "RSLC_tab: $rslc_tab\n";
print "ITAB:     $itab\n";
print "DIFF directory:  $diff_dir\n";
print "RMLI image:      $rmli\n";
print "adf window size: $adf_win\n";
print "adf exponent:    $adf_exp\n";
print "adf step:        $adf_step\n";
print "adf cc window:   $ccw\n";
print "display scale factor: $scale  exponent: $exp\n";

print LOG "\n$0  @ARGV\n";
print LOG "start: $time  log file: $log\n\n";
print LOG "RSLC_tab: $rslc_tab\n";
print LOG "ITAB:     $itab\n";
print LOG "DIFF directory:  $diff_dir\n";
print LOG "RMLI image:      $rmli\n";
print LOG "adf window size: $adf_win\n";
print LOG "adf exponent:    $adf_exp\n";
print LOG "adf step:        $adf_step\n";
print LOG "adf cc window:   $ccw\n";
print LOG "display scale factor: $scale  exponent: $exp\n\n";

$i = 1;
#read in the contents of the RSLC_TAB file and store in arrays
LINE: while (<RSLC_TAB>) {	#read lines of processing list file
  chomp $_;			#remove new line from record
  next LINE if /^$/; 		#skip blank lines in processing list
  next LINE if /^#/; 		#skip comments in processing list
  @fields = split;		#extract the scene identifier and other parameters on the line if present
  $slc[$i] = $fields[0];
  $slc_par[$i] = $fields[1];
  -e $slc[$i] or die "ERROR $0: slc image file does not exist: $slc[$i]\n";     
  -e $slc_par[$i] or die "ERROR $0: ISP image parameter file does not exist for slc: $slc_par[$i]\n";
  printf LOG "%2d  $slc[$i]  $slc_par[$i]\n",$i;
  $i++;
} 
$n = 1;

LINE: while (<ITAB>) {		#read lines of processing list file
  chomp $_;			#remove new line from record
  next LINE if /^$/; 		#skip blank lines in processing list
  next LINE if /^#/; 		#skip comments in processing list
  @fields = split;		#extract the scene identifier and other parameters on the line if present
  next LINE if ($fields[3] == 0); #do not unwrap interferograms with the layer flag set to 0
  $slc1 = $slc[$fields[0]];
  $slc1_par = $slc_par[$fields[0]];
  my ($s1, $dir1, $ext1) = fileparse($slc1, qr/\.[^.]*/); #extension is the last bit after the last period   

  $slc2 = $slc[$fields[1]];
  $slc2_par = $slc_par[$fields[1]];
  my ($s2, $dir2, $ext2) = fileparse($slc2, qr/\.[^.]*/); #extension is the last bit after the last period   

  $fn = $s1."_".$s2;
  $diff = $diff_dir."/".$fn.".diff";
  $off =  $diff_dir."/".$fn.".off";
  $adf_cc = $diff_dir."/".$fn.".adf.cc";
  $adf = $diff_dir."/".$fn.".adf.diff";
  
  $time = localtime;
  printf "\n*** diff. interferogram:%3d  $time ***\n",$n;
  print "SLC-1: $slc1   SLC1_par: $slc1_par\n";
  print "SLC-2: $slc2   SLC2_par: $slc2_par\n";
  print "DIFF interferogram:         $diff\n";
  print "interferogram parameters:   $off\n";
  print "adf filtered interferogram: $adf\n";
  print "adf correlation output:     $adf_cc\n\n"; 

  open(LOG,">>$log") or die "ERROR $0: cannot open mk_adf_2d log file: $log\n";
  printf LOG "\n*** diff. interferogram:%3d  $time ***\n",$n;
  print LOG "SLC-1: $slc1   SLC1_par: $slc1_par\n";
  print LOG "SLC-2: $slc2   SLC2_par: $slc2_par\n";
  print LOG "DIFF interferogram:         $diff\n";
  print LOG "interferogram parameters:   $off\n";
  print LOG "adf filtered interferogram: $adf\n";
  print LOG "adf correlation output:     $adf_cc\n\n";
  close LOG;

#read interferogram size from *.off interferogram parameter file
  @width = extract_param($off, "interferogram_width:");
  @lines = extract_param($off, "interferogram_azimuth_lines:");
  @rstart = extract_param($off, "first_nonzero_range_pixel:");
  @rpix = extract_param($off, "number_of_nonzero_range_pixels:");

  execute("adf $diff $adf $adf_cc $width[1] $adf_exp $adf_win $ccw $adf_step 0 0 .2", $log);

  if ($mli_dir ne ""){
    $mli2 = $mli_dir."/".$s2.".rmli";
    unless (-e $mli2){
      $mli2 = $mli_dir."/".$s2.".mli";
      -e $mli2 or die "MLI-2 does not exist: $mli2\n";
    }
    $rmli = $mli2;
  }

  execute("rasmph_pwr $adf $rmli $width[1] 1 1 0 1 1 $scale $exp", $log);
  execute("rascc $adf_cc $rmli $width[1] 1 1 0 1 1 $cc_min $cc_max $scale $exp", $log);
  $n++;
}

$time = localtime;
print "\n$0 processing end: $time\n";
open(LOG,">>$log") or die "ERROR $0: cannot open mk_adf_2d log file: $log\n";
print LOG "\n$0 processing end: $time\n";
close LOG;
exit 0;

sub execute{
  my ($command, $log) = @_;  
  if (-e $log){open(LOG,">>$log") or die "ERROR $0: cannot open log file: $log\n";}
  else {open(LOG,">$log") or die "ERROR $0 : cannot open log file: $log\n";} 
  LOG->autoflush; 
  print "$command\n";
  print LOG ("\n${command}\n");
  close LOG;  
  $exit = system("$command 1>> $log");
  $exit == 0 or die "ERROR $0: non-zero exit status: $command\n"
}

sub extract_param{
  my ($infile,$keyword) = @_;
  open(PAR_IN,$infile) || die "ERROR $0: cannot open parameter file: $infile\n";

  while(<PAR_IN>){
    chomp;
    @tokens = split;
    if($tokens[0] eq $keyword){close PAR_IN; return @tokens;}
  }
  close PAR_IN;
  die "ERROR $0: keyword $keyword not found in file: $infile\n";
}

