#!/usr/bin/perl

# Procedure to difference similar exposures. Not extremely reliable, 
# use at own risk! I typically do the intensity matching manually.

# 1) Get list of stellar positions
# 2) Align paired images based on WCS information
# 3) Do fine alignment based on stars
# 4) Perform psf matching on paired images
# 5) Perform intensity matching on paired images using known stars
# 5) Write out pre-differenced and differenced images,
#    to be (optionally) intensity matched by hand

# History
#  08July7  MM  created
#  08Sept3  MM  overhaul

#
# Detailed help message
#

use Getopt::Long;
use Text::Wrap;

@usage = ("v1.0  MM  02May2008\n\nUsage: imacsdiff (OBJECTS) \n\n");
@help = (
         "\t---------------\n ",
         "\tREQUIRED INPUTS\n ",
         "\t---------------\n ",
         "\tOBJECTS is a file containing all of the paired\n",
	 "\t(emission+continuum) exposures. For example: \n\n",
         "\taassfccd0001,aassfccd0002\n",
	 "\taassfccd0003,aassfccd0004\n",
	 "\twould subtract 2 from 1 and 4 from 3\n\n",
         "\t------\n ",
         "\tOUTPUT\n ",
         "\t------\n ",
         "\tThe output is an IRAF CL script named 'difference.cl'; run\n",
         "\tthis file at the cl> prompt with the following syntax:\n",
         "\tcl> cl < difference.cl\n\n",
         );


if ($#ARGV lt 1) {
    if ($#ARGV eq 0) {
        if ($ARGV[0] eq "--help") {
            print @usage;
	    print @help;
            print "\n\n";
            exit;
        }
    } else {
        die "@usage\For detailed help: imacsdiff --help\n\n";
    }
}

open OBJ, $ARGV[0];
@obj = <OBJ>;
close OBJ;

@diff=();

$num=0;
foreach (@obj) {  # Each PAIR of exposures #

## Clean out temporary files ##
    push @diff, "del stars.pos\n";
    push @diff, "del refim.fits\n";
    push @diff, "del othim.fits\n";
    push @diff, "del dkernel.fits\n";

    print "\n";
    $num=$num+1;
    @line=parsecom($_);

    print "Getting header info...this may take some time.\n";
    for $k (0..$#line) {   # Each exposure #
	print "Reading: st$line[$k].fits...\n";
	## Get Seeing FWHM ##
	@in=();
	open IN, "st$line[$k].fits";
	@in = <IN>;
	close IN;
	foreach (@in) {
	    if (/SIMPLE/) {
		@hline=parse($_);
		for $j (0..$#hline) {
		    if ($hline[$j] =~ /FWHMSIG/) {
			$fwhmerr[$k]=$hline[$j+2];
		    } elsif ($hline[$j] =~ /FWHM/) {
			$fwhm[$k]=$hline[$j+2];
		    }
		    if ($hline[$j] =~ /IMCMB001/) {
			$stars[$k]=$hline[$j+1];
			$stars[$k]=substr($stars[$k],1,length($stars[$k])-2);
		    }
		    

		}
		print "FWHM\[$k\] = $fwhm[$k]\n";
	    }
	}
    }
    print "Making reference star list...\n";
    ## Decide which will be reference frame ##

    if ($fwhm[0]>$fwhm[1]){
	$ref=$line[0];
	$oth=$line[1];
	$refstars=$stars[0];
	push @diff, "imcopy st$line[0] refim\n";
	push @diff, "imcopy st$line[1] othim\n";
    } else {
	$ref=$line[1];
	$oth=$line[0];
	$refstars=$stars[1];
	push @diff, "imcopy st$line[1] refim\n";
	push @diff, "imcopy st$line[0] othim\n";
    }

    open POSFILE, "$refstars.ref";
    @pos = <POSFILE>;
    close POSFILE;
    print "Trimming $refstars.ref --> diff$num.ref\n";
    # Trim reference star list to only include chip 2 #
    # - changed, include everything #
    @trim=();
    foreach (@pos){
	@posline=parse($_);
	if (($posline[0]>3200)&&($posline[0]<5400)&&($posline[1]>2700)&&($posline[1]<5800)) {
	push @trim, "$posline[0] $posline[1]\n";
	}
    }
    unlink <diff$num.ref>; 
    open OUT, ">diff$num.ref";
    print OUT @trim;
    close OUT;

    print "Writing differencing script...\n";
  ### First align positions based on WCS ###
    push @diff, "wregister othim refim othim interpolant=\"spline3\" verbose+ interactive- wcsinherit+ fitgeometry=\"general\" fluxconserve+\n";
  ### Now do fine sub-pixel centering with imalign ###
    push @diff, "imalign othim refim diff$num.ref othim interp_type=\"spline3\" verbose+ bigbox=11 boxsize=7 \n";
    
  ### psf-matching ###
    push @diff, "psfmatch othim refim diff$num.ref dkernel output=\"othim\" convolution=\"image\" verbose+ center+ background=median dnx=25 dny=25 pnx=15 pny=15 filter=\"replace\" threshold=0.1\n";

  ### Intensity matching ###

    ## First, create a position file from the existing .ref file ##
    push @diff, "wcsctran diff$num.ref stars.pos refim physical world formats=\"%H %h\"\n";
    push @diff, "mscred\n";

    if ($fwhm[0]>$fwhm[1]) {  # Make sure we're rescaling the continuum frame!! #
	push @diff, "imcopy refim diff$line[0]_1\n";
	push @diff, "imcopy othim diff$line[0]_2\n";

	push @diff, "mscimatch refim,othim stars.pos accept+ scale+ zero- box1=15 box2=21 lower=-100 niterate=3 sigma=2.0 bpm=\"\" interactive- verbose+\n";
	push @diff, "imgets othim MSCSCALE\n";
	push @diff, "imarith othim * real(imgets.value) othim\n";
	
	push @diff, "imarith refim - othim diff$line[0]\n";


    } else {
	push @diff, "imcopy refim diff$line[0]_2\n";
	push @diff, "imcopy othim diff$line[0]_1\n";

	push @diff, "mscimatch othim,refim stars.pos accept+ scale+ zero- box1=11 box2=21 lower=-100 niterate=3 sigma=2.0  bpm=\"\" interactive- verbose+\n";
	push @diff, "imgets refim MSCSCALE\n";
	push @diff, "imarith refim * real(imgets.value) refim\n";

	push @diff, "imarith othim - refim diff$line[0]\n";	
	
    }
    push @diff, "bye\n";
    
}


unlink <difference.cl>; #remove old scripts first
open OUT, ">difference.cl";
print OUT @diff;
close OUT;

print fill("\t","",("Now enter IRAF and run 'difference.cl':\n cl> cl <
difference.cl\n "));
print "\n";


#######################

sub mode {
    my($mode);
    
    ## First, find the most populated bin from 0.0-5.0 in 0.1 steps ##
    $bestbin=0.0;
    $bestnum=0;
    $bin=-0.1;
    for $l (0..500){
	$bin+=0.1;
	$num=0;
	for $m (0..$#psf){
	    if (($psf[$m]>($bin-0.05))&&($psf[$m]<($bin+0.05))) { $num+=1 }
	}
	if ($num>$bestnum){
	    $bestnum=$num;
	    $bestbin=($bin);
	}
    }
    
    ## Now we know coarse mode... ##
    ## Take the preferred bin and +/- 1 to get average ##
    
    $mode=0.0;
    $num=0;
    for $m (0..$#psf){
	if (($psf[$m]>($bestbin-1.0))&&($psf[$m]<($bestbin+1.0))) {
	    $mode+=$psf[$m];
	    $num+=1;
	}
    }
    $mode=$mode/$num;
    
    return($mode);
}

#######################

sub parse {
    my(@parsed);
    @parsed = split(/\s+/,$_[0]);
    chomp(@parsed);
    #remove whitespace at beginning of line, if any
    while ($parsed[0] eq "") {shift(@parsed)}
    return(@parsed);
}

##########################
# @array = PARSECOM($line)
# Parse by commas
# 08feb11  DSNR  created
##########################

sub parsecom {
    my(@parsed);
    @parsed = split(/,+/,$_[0]);
    chomp(@parsed);
    #remove whitespace at beginning of line, if any
    while ($parsed[0] eq "") {shift(@parsed)}
    return(@parsed);
}
