#!/usr/bin/perl
#
use Statistics::OLS;
use Math::FFT;
use Math::Stat;
use Math::Spline qw(spline linsearch binsearch);
use Math::Derivative qw(Derivative2);
use Math::Approx;
use Astro::FITS::CFITSIO qw( :longnames :constants );
use PDL;
use PDL::Fit::Polynomial; 
use PDL::Filter::Linear;
use PGPLOT;  # Load PGPLOT module
use PDL::Fit::Gaussian;
use PDL::Slatec;
use PDL::Image2D;
#use PDL::Matrix;

#$F3D=$ENV{HIIEXPLORER_PATH};  $F3D=$ENV{HIIEXPLORER_PATH};  require("$F3D/my.pl"); #("$F3D/scripts/my.pl"); # "/work1/ssa/perl/MY/my.pl";
$F3D=$ENV{HIIEXPLORER_PATH};  $F3D=$ENV{HIIEXPLORER_PATH};  require("$F3D/my.pl"); #("$F3D/scripts/my.pl"); # "/home/sanchez/sda2/code/R3D/my.pl";
#/home/sanchez/3DSoft_Ubuntu/R3D/my.pl";


if ($#ARGV<6) {
    print "USE: isophot_seg.pl map.fits XC YC BOX NLEVELS MIN_FLUX SEGFILE.fits DIFFUSE_MASK.fits\n";
    exit;
}

$Ha_file=$ARGV[0];
$xc=int($ARGV[1]);
$yc=int($ARGV[2]);
$box=$ARGV[3];
#$min_dist=$ARGV[4];
$NC=$ARGV[4];
$MIN_FLUX=$ARGV[5];
$segfile=$ARGV[6];
$maskfile=$ARGV[7];



$Ha_map=rfits($Ha_file);
($nx,$ny)=$Ha_map->dims;
$seg_map=zeroes($nx,$ny);
$mask_map=ones($nx,$ny);

#$Ha_cut=$Ha_map-$MIN_FLUX;
($ip,$jp)=find_max($xc,$yc,$box);
$f_max=$Ha_map->at($ip,$jp);

#$Ha_cut=med2df($Ha_map,$box,$box,{Boundary => Reflect});

$Ha_map->inplace->setvaltobad(0);
$Ha_map->inplace->setbadtoval(0.001);
$Ha_cut=abs($Ha_map);
$Ha_cut2=med2df($Ha_cut,5,5,{Boundary => Reflect});
$lHa_map=$Ha_cut2->inplace->log10;
if ($MIN_FLUX>0) {
    $f_map=($lHa_map-log10(abs($MIN_FLUX)))/(log10($f_max)-log10(abs($MIN_FLUX)))*$NC;
} else {
#    $MIN_FLUX=0.001;
    $f_map=($lHa_map)/(log10($f_max))*$NC;
}
@stats=stats($f_map);

$f_map=$f_map-$stats[3];
$f_map->wfits("fmap.fits");
#print "$MIN_FLUX $f_max | @stats\n";

for ($i=0;$i<$NC;$i++) {
    $xp[$i]=0;
    $yp[$i]=0;
    $np[$i]=0;
    $max_dist[$i]=0;
}

$nup=0;
$isec_max=0;
for ($i=0;$i<$nx;$i++) {
    for ($j=0;$j<$ny;$j++) {
	$val=$lHa_map->at($i,$j);
	if (($val>log10($MIN_FLUX))&&($val<1e30)) {
	    $sec=$f_map->at($i,$j);
	    $isec=int($sec)+1;
	    $msec=0;
	} else {
	    $isec=1;
	    $msec=1;
	}
	$dist=sqrt(($i-$ip)**2+($j-$jp)**2);
	$K=$N[$isec];
	$D[$isec][$K]=$dist;
	$F[$isec][$K]=$Ha_map->at($i,$j);
	$N[$isec]=$N[$isec]+1;
	if ($isec>$isec_max) {
	    $isec_max=$isec;
	}
	set($seg_map,$i,$j,$isec);
	set($mask_map,$i,$j,$msec);
    }
}

$if_rad=0;
if ($if_rad==1) {
$rad_pt=$segfile;
$rad_pt =~ s/fits/pt/;
$rad_pt =~ s/fit/pt/;
open(FH,">$rad_pt");
for ($i=1;$i<=$isec_max;$i++) {
    if ($N[$i]>1) {
	my @d;
	for ($j=0;$j<$N[$i];$j++) {
	    $d[$j]=$D[$i][$j];
	}
	@stats=stats(pdl(@d));
	$dnow=$stats[0];
	$sdnow=$stats[1];
	my @f;
	for ($j=0;$j<$N[$i];$j++) {
	    $f[$j]=$F[$i][$j];
	}
	@stats=stats(pdl(@f));
	$fnow=$stats[0];
	$sfnow=$stats[1];
    } else {
	if ($N[$i]==0) {
	    $dnow=0;
	    $sdnow=0;
	    $fnow=0;
	    $sfnow=0;
	} else {
	    $dnow=0;
	    $sdnow=0;
	    $fnow=$F[$i][0];
	    $sfnow=0;
	}
    }    
    print FH "$i $dnow $sdnow $fnow $sfnow\n";
}
close(FH);
}

$Ha_map->wfits("e_org.fits.gz");
$seg_map->wfits($segfile);
$mask_map->wfits($maskfile);


#
# We analyze the elliptical structure
#

@stats=stats($seg_map);
$seg_max=$stats[4];

my @flux;
my @x_flux; my @y_flux;
my @xx_flux; my @yy_flux;
my @xy_flux;
my @ns;
my @FLUX;
my @XX,@YY;
for ($i=0;$i<$nx;$i++) {
    for ($j=0;$j<$ny;$j++) {
	$is=$seg_map->at($i,$j);
	$val=$Ha_map->at($i,$j);
	$ns_now=$ns[$is];
	$FLUX[$is][$ns_now]=$val;	
	$XX[$is][$ns_now]=$i;
	$YY[$is][$ns_now]=$j;
	$ns_now++;
	$ns[$is]=$ns_now;
	$flux[$is]=$flux[$is]+$val;
	$x_flux[$is]=$x_flux[$is]+$i*$val;
	$y_flux[$is]=$y_flux[$is]+$j*$val;
	$xx_flux[$is]=$xx_flux[$is]+$i*$i*$val;
	$yy_flux[$is]=$yy_flux[$is]+$j*$j*$val;
	$xy_flux[$is]=$xy_flux[$is]+$i*$j*$val;
    }
}    


open(OUT,">ellipse.sb");
print OUT "#x_flux y_flux r flux_med flux_sig e pa sig_r\n";
my @flux_med,@flux_sig,@r,@sig_r;
for ($is=$seg_max;$is>1;$is--) {
    my @tmp;
    my @tmp_r;
    for ($j=0;$j<$ns[$is];$j++) {
	$tmp[$j]=$FLUX[$is][$j];
	$tmp_r[$j]=sqrt(($XX[$is][$j]-$xc)**2+($YY[$is][$j]-$yc)**2);
#	print "$is $tmp[$j]\n";
    }
    $flux_med[$is]=mean(@tmp);
    $flux_sig[$is]=sigma(@tmp);
    $r[$is]=median(@tmp_r);
    $sig_r[$is]=sigma(@tmp_r);
}
@stats=stats($seg_map);
$seg_max=$stats[4];

open(MOD,">model.slice");
$k=0;
$model=zeroes($nx,$ny);
for ($is=$seg_max;$is>1;$is--) {
    if ($flux[$is]>0) {
	$x_flux[$is]=$x_flux[$is]/$flux[$is];
	$y_flux[$is]=$y_flux[$is]/$flux[$is];
	$xx_flux[$is]=$xx_flux[$is]/$flux[$is];
	$yy_flux[$is]=$yy_flux[$is]/$flux[$is];
	$xy_flux[$is]=$xy_flux[$is]/$flux[$is];
    }
    $xx=$xx_flux[$is]-$x_flux[$is]*$x_flux[$is];
    $yy=$yy_flux[$is]-$y_flux[$is]*$y_flux[$is];
    $xy=$xy_flux[$is]-$x_flux[$is]*$y_flux[$is]; 
    $pa=0.5*(real_atan(($xx-$yy),2*$xy));
    $a=sqrt(abs(($xx+$yy)/2+sqrt((($xx-$yy)/2)**2+$xy*$xy)));
    $b=sqrt(abs(($xx+$yy)/2-sqrt((($xx-$yy)/2)**2+$xy*$xy)));
    if ($a>0) {
	$e=1-($b/$a)**2;
    } else {
	$e=0;
    }
    $dist_c=sqrt(($x_flux[$is]-$xc)**2+($y_flux[$is]-$yc)**2);
#    if (($dist_c<$box)&&($r[$is]<($nx-$xc))) {	
    if (($dist_c<2*$box)&&($ns[$is]>0.3*(2*3.1416*$r[$is]))) {	
#    if (($flux_med[$is]>$MIN_FLUX)&&($dist_c<$box)) {	
	printf OUT ("%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n",$x_flux[$is],$y_flux[$is],$r[$is],$flux_med[$is],$flux_sig[$is],$e,$pa,$ns[$is]);
	printf ("%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n",$x_flux[$is],$y_flux[$is],$r[$is],$flux_med[$is],$flux_sig[$is],$e,$pa,$ns[$is]);
   
	for ($angle=0;$angle<360;$angle=$angle+10) {
	    $ang=($angle)/180*3.14159;
#	    $pa_n=(90+$pa)/180*3.14159,
	    $pa_n=($pa)/180*3.14159,
	    $xx=$r[$is]*cos($ang);
	    $yy=$r[$is]*(1-($e**2))*sin($ang);
	    $xp=$xc+$xx*cos($pa_n)-$yy*sin($pa_n);
	    $yp=$yc+$xx*sin($pa_n)+$yy*cos($pa_n);
	    $ii=int($xp);
	    $jj=int($yp);
	    if (($ii>-1)&&($ii<$nx)&&($jj>-1)&&($jj<$ny)) {
		$val=$model->at($ii,$jj);
		if ($val==0) {
		    $val=$flux_med[$is];
		    set($model,$ii,$jj,$val);
		    print MOD "$k $xp $yp $flux_med[$is]\n";
		    $k++;
		}
	    }
	}

    }
}
close(OUT);
$nx_max=$nx-1; $ny_max=$ny-1;
print MOD "$k 0 0 0\n"; $k++;
print MOD "$k 0 $ny_max 0\n"; $k++;
print MOD "$k $nx_max 0 0\n"; $k++;
print MOD "$k $nx_max $ny_max 0\n"; $k++;
close(MOD);
$call="interpol -if model.slice -of model.fits -dp 1 -nc 4 -gf 3 -go 1e-20 -noask";
system($call);
$mod=rfits("model.fits");
$mod->inplace->setnantobad;
$mod->inplace->setbadtoval(0);
($nx1,$ny1)=$mod->dims();
$nx_m=$nx1-1;
$ny_m=$ny1-1;
if ($nx_m>$nx-1) {
    $nx_m=$nx-1;
}
if ($ny_m>$ny-1) {
    $ny_m=$ny-1;
}

$sec=$mod->slice("0:$nx_m,0:$ny_m");
$sec2=$model->slice("0:$nx_m,0:$ny_m");
$sec2 .= $sec;

$model->wfits("e_mod.fits.gz");
$res=$Ha_map-$model;
$res->wfits("e_res.fits.gz");

#
# model image
#

##





exit;

# 1 larger than nearby
# 0 equal
# -1 smaller than nearby

sub find_max {
    my $i=$_[0];
    my $j=$_[1];
    my $box=$_[2];
    my $i1=$i-$box;
    my $i2=$i+$box+1;
    my $j1=$j-$box;
    my $j2=$j+$box+1;
    if ($i1<0) {
	$i1=0;
	$i2=$i1+$box+2;
    }
    if ($i2>$nx-$box) {
	$i2=$nx-$box;
	$i1=$i2-$box-2;
    }
    if ($j1<0) {
	$j1=0;
	$j2=$j1+$box+2;
    }
    if ($j2>$ny-$box) {
	$j2=$ny-$box;
	$j1=$j2-$box-2;
    }
    my @a=($i,$j);
    my $max=-1e30;
    for ($ii=$i1;$ii<$i2;$ii++) {
	for ($jj=$j1;$jj<$j2;$jj++) {
	    my $val=$Ha_map->at($ii,$jj);
	    if ($val>$max) {
		$max=$val;
		@a=($ii,$jj);
	    }
	}
    }
    return @a;
}


sub real_atan {
    my $x = $_[0];
    my $y = $_[1];
    my $angle;
    if ($y==0) {
	if ($x>=0) {
	    $angle=0;
	} else {
	    $angle=3.14159;
	}
    } else {
        if ($x==0) {
	    if ($y>=0) {
		$angle=3.14159/2;
	    } else {
		$angle=-3.14159/2;
	    }
	} else {
	    if (($x>0)&&($y>0)) {
		$angle=atan($y/$x);
	    }
	    if ($x<0) {
		$angle=3.14159+atan($y/$x);
	    }
	    if (($x>0)&&($y<0)) {
		$angle=2*3.14159+atan($y/$x);
	    }

	}

    }
    $angle=$angle*(180/3.14159);
#    my $out=$angle->at(0);
    $out=$angle;
    return $out;
}


