#!/usr/bin/env perl
# $Id: mitiPlot 1595 2007-05-23 21:29:22Z denneau $

use strict;
use warnings;

use Getopt::Long;
use Pod::Usage;
use Params::Validate;
use File::Temp qw(tempfile);

use PS::MOPS::MITI;
use Astro::SLA;
use PS::MOPS::Constants qw(:all);


# RA/DEC of ecliptic at equally-spaced ecliptic longitudes.
my $ECLDATA = <<"EOF";
0 -0.0445318387031217
4.4866829748582, 1.94228500990418
9.0866143176195, 3.91662834051301
13.7081469364301, 5.86570064476499
18.3617543449775, 7.77663218647298
23.0573446661801, 9.63645855427837
27.8040374770556, 11.4321155234863
32.6099169418103, 13.150457333866
37.4817620197704, 14.7783044329016
42.424759588699, 16.3025262733881
47.4422125414467, 17.7101636513999
52.5352618743822, 18.9885930924382
57.7026486238976, 20.1257327761744
62.9405468681325, 21.1102854253362
68.2425011682125, 21.9320087115372
73.5994990200881, 22.5819986026821
79.0001999037522, 23.0529665495992
84.4313273275887, 23.3394885215417
89.8782105392245, 23.4382036254024
95.3254416795243, 23.3479429769241
100.757596495161, 23.0697755729854
106.159956484432, 22.6069663180431
111.519170116041, 21.9648506423358
116.823800591965, 21.1506386271938
122.064725036842, 20.1731677607994
127.235370843988, 19.0426265290635
132.331794770044, 17.7702709064714
137.352625811769, 16.3681530215682
142.298902171408, 14.8488767953904
147.173835677511, 13.225390229596
151.982535057163, 11.5108191226012
156.731714199398, 9.71834288368728
161.429404745432, 7.86111004940616
166.084685364166, 5.95218908453372
170.707433808776, 4.00454891249862
175.308102740247, 2.03106313609774
179.897516454345, 0.0445318387031245
184.486682974858, -1.94228500990418
189.086614317619, -3.91662834051301
193.70814693643, -5.86570064476498
198.361754344977, -7.77663218647298
203.05734466618, -9.63645855427836
207.804037477056, -11.4321155234863
212.60991694181, -13.150457333866
217.48176201977, -14.7783044329016
222.424759588699, -16.3025262733881
227.442212541447, -17.7101636513999
232.535261874382, -18.9885930924382
237.702648623898, -20.1257327761744
242.940546868132, -21.1102854253362
248.242501168212, -21.9320087115372
253.599499020088, -22.5819986026821
259.000199903752, -23.0529665495992
264.431327327589, -23.3394885215417
269.878210539225, -23.4382036254024
275.325441679524, -23.3479429769241
280.757596495161, -23.0697755729854
286.159956484432, -22.6069663180431
291.519170116041, -21.9648506423358
296.823800591965, -21.1506386271938
302.064725036842, -20.1731677607994
307.235370843988, -19.0426265290635
312.331794770044, -17.7702709064714
317.352625811769, -16.3681530215682
322.298902171408, -14.8488767953904
327.173835677511, -13.225390229596
331.982535057163, -11.5108191226012
336.731714199398, -9.71834288368729
341.429404745432, -7.86111004940616
346.084685364166, -5.95218908453371
350.707433808776, -4.00454891249864
355.308102740247, -2.03106313609773
359.897516454345, -0.0445318387031273
e
EOF


my $GALDATA = <<"EOF";
6.45084943177178, 62.7257286088913
15.2008162650177, 62.8523249038659
23.865760609291, 62.437746711684
32.1504677662169, 61.5057257884202
39.8380069341964, 60.1048837788974
46.8132973004165, 58.2977025548179
53.051549890195, 56.1497103355758
58.5895671777465, 53.722008160128
63.4968959388044, 51.0675946955493
67.8547647012539, 48.2304656684141
71.7435740121524, 45.2462374857647
75.236768230833, 42.1433844359169
78.3986248633776, 38.9445785323855
81.2841329341069, 35.6679016848586
83.9398325021262, 32.327856083561
86.404996225917, 28.9361720130301
88.7128457704251, 25.5024404011124
90.8916691051554, 22.0346039645284
92.9657940941835, 18.5393384935846
94.9564164922089, 15.0223506811306
96.8822987762854, 11.4886135495434
98.7603625182753, 7.94255592153611
100.60619778937, 4.38821875043506
102.434511730714, 0.829388426920471
104.259536570614, -2.73028471662084
106.095415796417, -6.28717570417367
107.95658624356, -9.83757565946769
109.858173680423, -13.3775777564479
111.81642006694, -16.9029517440425
113.849161972022, -20.4089994702755
115.976381420741, -23.8903822636836
118.220852169126, -27.3409087225341
120.608904904338, -30.753268279876
123.171331724676, -34.1186917546652
125.944438656216, -37.4265150335938
128.971225670772, -40.6636165968337
132.302609651869, -43.8136954809567
135.998477375045, -46.8563576112698
140.128116006095, -49.7659943248991
144.769157386181, -52.5104853226327
150.003550892492, -55.0498704125483
155.908353137957, -57.3353529223038
162.538820658822, -59.3093496026051
169.902742107728, -60.9077100646352
177.930070944811, -62.0653516323958
186.450849431772, -62.7257286088913
195.200816265018, -62.8523249038659
203.865760609291, -62.437746711684
212.150467766217, -61.5057257884202
219.838006934196, -60.1048837788974
226.813297300417, -58.2977025548179
233.051549890195, -56.1497103355758
238.589567177747, -53.722008160128
243.496895938804, -51.0675946955493
247.854764701254, -48.2304656684141
251.743574012152, -45.2462374857647
255.236768230833, -42.1433844359169
258.398624863378, -38.9445785323855
261.284132934107, -35.6679016848586
263.939832502126, -32.327856083561
266.404996225917, -28.9361720130301
268.712845770425, -25.5024404011124
270.891669105155, -22.0346039645284
272.965794094183, -18.5393384935846
274.956416492209, -15.0223506811306
276.882298776285, -11.4886135495434
278.760362518275, -7.94255592153611
280.60619778937, -4.38821875043504
282.434511730714, -0.829388426920464
284.259536570614, 2.73028471662085
286.095415796417, 6.28717570417367
287.95658624356, 9.83757565946768
289.858173680423, 13.3775777564479
291.81642006694, 16.9029517440425
293.849161972022, 20.4089994702755
295.976381420741, 23.8903822636836
298.220852169126, 27.3409087225341
300.608904904338, 30.753268279876
303.171331724676, 34.1186917546652
305.944438656216, 37.4265150335938
308.971225670772, 40.6636165968336
312.302609651869, 43.8136954809567
315.998477375045, 46.8563576112698
320.128116006095, 49.7659943248992
324.769157386182, 52.5104853226327
330.003550892492, 55.0498704125483
335.908353137957, 57.3353529223038
342.538820658822, 59.3093496026051
349.902742107728, 60.9077100646352
357.930070944811, 62.0653516323958
e
EOF

my $SUNDATA = <<"EOF";
180 0
e
EOF

my $MOONDATA = <<"EOF";
200 0
e
EOF


my $nodelete;
my $title;
my $xu = '';     # x units
my $yu = '';     # y units
my ($xmin, $xmax, $ymin, $ymax);

my $show_sun;
my $show_moon;
my $bynight;        # aggregate by night (integer epoch)
my $seghack;
my $autoscale;
my $terminal;
my $postscript;
my $postscriptc;
my $eps;
my $epsc;
my $png;
my $nokey;
my $help;

my $size_str = "140x80";

GetOptions(
    'title=s' => \$title,
    'xu=s' => \$xu,
    'yu=s' => \$yu,
    'xmin=f' => \$xmin,
    'xmax=f' => \$xmax,
    'ymin=f' => \$ymin,
    'ymax=f' => \$ymax,

    sun => \$show_sun,
    moon => \$show_moon,
    bynight => \$bynight,   
    seghack => \$seghack,           # hack to segregate based on last column
    autoscale => \$autoscale,
    'terminal=s' => \$terminal,
    postscriptc => \$postscriptc,
    postscript => \$postscript,
    'size=s' => \$size_str,
    eps => \$eps,
    epsc => \$epsc,
    png => \$png,
    nokey => \$nokey,
    nodelete => \$nodelete,
    help => \$help,
) or pod2usage(2);
pod2usage(-verbose => 2) if $help;


# Scrub opts.
$terminal = 'postscript solid' if $postscript or $eps;
$terminal = 'postscript enhanced color solid' if $postscriptc or $epsc;
$terminal = 'png' if $png;


# gnuplot linetype pointtype vars
my $lt = 1;
my $pt = 1;
sub _plot {
    # Use gnuplot to plot detection or observation data.  A descriptor
    # for the data to be plotted is passed in as data => [], which should
    # be an arrayref of arrayrefs.  Each array is concatenated into a single
    # inline plot for gnuplot using "plot '-'".
    my %args = validate(@_, {
        data => 1,      # array ref of array refs
        xrange => 0,
        yrange => 0,
        cols => 0,
        title => 0,
        keylist => 0,
    });
    my $xrange = defined($args{xrange}) ? "set xrange $args{xrange} reverse" : 'set xrange [] reverse';
    my $yrange = defined($args{yrange}) ? "set yrange $args{yrange}" : '';
    my $cols = $args{cols};
    my $title_str = ($title or $args{title} or "Untitled");

    # Write data to tmp file; call gnuplot in bg; rm tmp file.
    my ($fh, $filename) = tempfile('/tmp/mitiPlotXXXXX', SUFFIX => '.txt');

    $size_str =~ s/x/,/;        # convert AxB to a,b
    print $fh "set terminal $terminal size $size_str font arial 6\n" if $terminal;
    print $fh "set nokey\n" if $nokey;

    printf $fh <<"GNUPLOT";
set xzeroaxis
$xrange
$yrange
plot \\
GNUPLOT

    my $got_data;   # flag if we have any data to plot
    my $last;       # indicates last iter through data list
    my $keyindex = 0;   # index into keys list, for per-object type titles in GNUPlot key
    my $keytitle;

    # Ecliptic.
    print $fh <<"EOF";
"-" using 1:2 with lines notitle lc rgb "grey",\\
EOF

    # Galactic pane.
    print $fh <<"EOF";
"-" using 1:2 with lines notitle lc rgb "blue",\\
EOF

    if ($show_sun) {
        print $fh <<"EOF";
"-" using 1:2 with points pt 7 ps 2 lc rgb "gold" notitle,\\
EOF
    }

    if ($show_moon) {
        print $fh <<"EOF";
"-" using 1:2 with points pt 7 ps 2 lc rgb "grey" notitle,\\
EOF
    }

    foreach my $d (@{$args{data}}) {
        $last = ($d == $args{data}->[-1]);
        $got_data = 1 if @{$d};     # test we actually have some data

        $keytitle = $args{keylist} ? $args{keylist}->[$keyindex] : $title;

#"-" using $cols title '$keytitle' lt $lt pt $pt%s with points
        printf $fh <<"GNUPLOT", ($last ? '' : ',\\');
"-" using $cols notitle with points pt 5 ps 1 lc rgb "green" %s
GNUPLOT

        $lt = $lt % 16 + 1;
        $pt = $pt % 16 + 1;
        $keyindex++;
    }

    print $fh $ECLDATA;
    print $fh $GALDATA;
    print $fh $SUNDATA if $show_sun;
    print $fh $MOONDATA if $show_moon;
    foreach my $d (@{$args{data}}) {
        print $fh @{$d};
        print $fh "e\n";    # end of data
    }

    close $fh;

    if ($got_data) {
        if ($terminal) {
            system "gnuplot $filename";
        }
        else {
            system "gnuplot -persist $filename";
        }
        (unlink $filename or warn "can't unlink $filename") unless $nodelete;
    }
}



# Start of program.

# Read MITI data from STDIN:
# ID EPOCH_MJD RA_DEG DEC_DEG MAG OBSCODE OBJECT_NAME
my $line;
my %datadata;

my ($id, $epoch_mjd, $ra_deg, $dec_deg, $mag, $obscode, $object);
my $prefix;

while (defined($line = <>)) {
    next if $line =~ /^#/;  # skip comments
    ($id, $epoch_mjd, $ra_deg, $dec_deg, $mag, $obscode, $object) = split /\s+/, $line;

    if ($bynight) {
        $prefix = int($epoch_mjd);
    }
    elsif ($seghack and $object) {
        $prefix = substr($object, 0, 2);
        $prefix = 'XX' unless $prefix =~ m/^(S0|S\d|ST|St|SC|Sc|SS)/;
    }
    else {
        $prefix = '';        # dummy to aggregate all data in one list
    }
    push @{$datadata{$prefix}}, "$ra_deg, $dec_deg\n";
}

my ($ra_rad, $dec_rad, $diam_rad);
use constant SUN => 0;
use constant MOON => 3;
if (defined($epoch_mjd) and $show_sun) {
    my ($ra_deg, $dec_deg, $diam_deg);
    # Load sun's coordinates.
    slaRdplan($epoch_mjd, SUN, 0, 0, $ra_rad, $dec_rad, $diam_rad);
    $ra_deg = $ra_rad * $DEG_PER_RAD;
    $dec_deg = $dec_rad * $DEG_PER_RAD;
    $diam_deg = $diam_rad * $DEG_PER_RAD;
    $SUNDATA = <<"EOF";
$ra_deg $dec_deg
e
EOF
}

if (defined($epoch_mjd) and $show_moon) {
    my ($ra_deg, $dec_deg, $diam_deg);
    # Load moon's coordinates.
    slaRdplan($epoch_mjd, MOON, 0, 0, $ra_rad, $dec_rad, $diam_rad);
    $ra_deg = $ra_rad * $DEG_PER_RAD;
    $dec_deg = $dec_rad * $DEG_PER_RAD;
    $diam_deg = $diam_rad * $DEG_PER_RAD;
    $MOONDATA = <<"EOF";
$ra_deg $dec_deg
e
EOF
}

if (%datadata) { 
    # Plot wants ARRAYREF of ARRAYREFs.
    my @args = (
#        data => [\@data],
        data => [ map { $datadata{$_} } sort keys %datadata],
        keylist => [ sort keys %datadata ],
        cols => '1:2', 
        title => ($title or 'Data'),
    );
    if (defined($xmin)) {
        push @args, xrange => "[$xmin:$xmax]";
    }
    if (defined($ymin)) {
        push @args, yrange => "[$ymin:$ymax]";
    }
    else {
        push @args, (xrange => '[0:360]', yrange => '[-90:90]') unless $autoscale; 
    }
    _plot(@args);
}

exit();

=head1 NAME

miniPlot - Program to plot MITI data using GNUPlot

=head1 SYNOPSIS

miniPlot [--title "TITLE"] [--autoscale]
    [--terminal DEVICE] [--postscript|postscriptc|eps|epsc] [--png] [--nokey]
    [--nodelete]
    [--help]

    --title "TITLE" : use TITLE as plot title
    --xu XUNITS : specify X units string
    --yu UUNITS : specify Y units string
    --autoscale : always autoscale RA and DEC (--mjd by default scales to full sky)
    --terminal DEVICE : set gnuplot terminal to DEVICE; write output to stdout
    --postscript|eps : abbreviation for "--terminal postscript"
    --postscriptc|epsc : abbreviation for "--terminal 'postscript enhanced color'"
    --png : abbreviation for "--terminal png"
    --nokey : 'set nokey' in GNUPlot; hides key/legend
    --nodelete : don't delete temporary GNUPlot files (for debugging)
    --help : show usage and examples in manpage format

=head1 DESCRIPTION

Reads MITI data in STDIN and plots using GNUPlot.  Each line of data should be
in the format

ID EPOCH_MJD RA_DEG DEC_DEG MAG OBSCODE OBJECT_ID

only RA_DEG and DEC_DEG really matter though.

=head1 SEE ALSO

PS::MOPS::MITI

=cut

