#!/usr/local/bin/perl  
# @(#) read_xml_series 1.2 08/24/00 Ken Hurst
# This is a pretty much dead-simple parser for GPS time series XML files.
# It simply reads the XML file and prints it out as a space-delimited
# table.  ALL THE PARSING HAPPENS ON ONE LINE (see below). Access to the
# contents of the file is through a hash table like this:
#   print "$station->{location}->[$i]->{lon}->{estimate} \n ";

# It does demand that the input XML file be well-formed, but does not yet
# validate it against the published DTD (Document Type Definition) available
# at ftp://sidehow.jpl.nasa.gov/pub/hurst/DTD/GPS_series.01.dtd

# This perl program is provided in the hope that people will take it and
# modify it to do what they want with the XMLfiles.
# It requires the existance of the Simple.pm and Parser.pm packages available
# from CPAN.

# Ken Hurst June 2000 JPL

use XML::Simple;

$SIG{INT} = \&catch_ctlC;

my $Usage =<<'End_of_Usage;';
Usage:
	read_xml_series [-h] [-headers] [+stationID] [+info] [+location] 
		[+velocity] [+repeatability] [+fit] [+series]  XMLfile

Without any arguments will print a table to stdout with headers and with all 
information in the file.

The XMLfile can be compressed in which case it shoud have a .gz or .Z extension.

-headers 	turns off headers
+series etc	turns on location, velocity, repeatabilities, series etc. If 
		one is turned on, any not explicitly turned on will be off. 

EXAMPLES:
	If you want just locations and velocities with no headers, use
		read_series -headers +location +velocity XMLfile
	If you want a table of series with headers, use
		read_series +series XMLfile

End_of_Usage;

if ($#ARGV < 0) {
  die "$Usage\n";
}
my $use_headers=1;
my $write_id=0;
my $write_info=0;
my $write_location=0;
my $write_velocity=0;
my $write_repeat=0;
my $write_fit=0;
my $write_series=0;
my $select_out=0;
while (defined($ARGV[0]) and $ARGV[0] =~ /^[-+]/) {
  my $opt = shift;
  if ($opt =~ /-[hH]$/) {
    print $Usage;
    exit(-1);
  } elsif ($opt =~ /-head/ ){
    $use_headers=0;
  } elsif ($opt =~ /\+sta/ ){
    $write_id=1;
    $select_out=1;
  } elsif ($opt =~ /\+info/ ){
    $write_info=1;
    $select_out=1;
  } elsif ($opt =~ /\+loc/ ){
    $write_location=1;
    $select_out=1;
  } elsif ($opt =~ /\+vel/ ){
    $write_velocity=1;
    $select_out=1;
  } elsif ($opt =~ /\+rep/ ){
    $write_repeat=1;
    $select_out=1;
  } elsif ($opt =~ /\+fit/ ){
    $write_fit=1;
    $select_out=1;
  } elsif ($opt =~ /\+ser/ ){
    $write_series=1;
    $select_out=1;
  } else {
    print "unrecognized switch: $opt\n";
    print $Usage;
    exit(-1);
  }
}
if (! $select_out) {    #nothing selected - turn it all on
  $write_id=1;
  $write_info=1;
  $write_location=1;
  $write_velocity=1;
  $write_repeat=1;
  $write_fit=1;
  $write_series=1;
}

$tmpcom=0;
if ($ARGV[0] =~ /[zZ]$/) {
  $XMLfname="tmp_read_series.$$";
  $done=`zcat $ARGV[0] > $XMLfname`;
  $tmpcomp=1;
} else {
  $XMLfname=$ARGV[0];
}


#-----------------------------------------------------------------------------
# ALL THE PARSING WORK IS DONE HERE
# this single line slurps up the whole file  

my $station = XMLin($XMLfname, searchpath=>'.', forcearray => ['location', 'velocity', 'repeatability']);

#-----------------------------------------------------------------------------

my $nloc = @{$station->{location}};
my $nvel = @{$station->{velocity}};
my $nrep = @{$station->{repeatability}};
my $nseries = @{$station->{series}};
my $ncomment = @{$station->{info}->{comment}};

if ($write_id) {
  if ($use_headers) {
    print "#station_name epoch\n"
  }

  #This is how we access individual pieces of information
  print "$station->{name} $station->{epoch} $station->{reference_frame}\n";
}

if ($write_info){
  if (defined $station->{info}->{analysis_version}) {
    print "analysis version = $station->{info}->{analysis_version}\n";
  }
  print "analysis date = $station->{info}->{analysis_date}\n";
  print "contact = $station->{info}->{contact}\n";
  if (defined $station->{info}->{institution}) {
    print "institution = $station->{info}->{institution}\n";
  }
  if (defined $station->{info}->{software_name}) {
    print "software name = $station->{info}->{software_name}\n";
  }
  if ($ncomment==1) {
    print "info comment = $station->{info}->{comment}\n";
  } else {
    for ($i=0;$i<$ncomment;$i++) {
      print "info comment = $station->{info}->{comment}->[$i]\n",
    }
  }
}



if ($write_location) {
  $head1="#year     event evtype    lon               err       lat              err     elev           err     lonlat    lonrad    latrad     x                         err               y                   err                z                      err";
    if ($use_headers) {
      print "$head1\n";
      printf "#                         %s           %s    %s          %s  %s %s   %s                                 %s                    %s            %s              %s             %s                 %s\n",
          $station->{location}->[0]->{lon}->{est_units},
          $station->{location}->[0]->{lon}->{sig_units},
          $station->{location}->[0]->{lat}->{est_units},
          $station->{location}->[0]->{lat}->{sig_units},
          $station->{location}->[0]->{height}->{est_units},
          $station->{location}->[0]->{height}->{ellipsoid},
          $station->{location}->[0]->{height}->{sig_units},
          $station->{location}->[0]->{x}->{units},
          $station->{location}->[0]->{x}->{units},
          $station->{location}->[0]->{y}->{units},
          $station->{location}->[0]->{y}->{units},
          $station->{location}->[0]->{z}->{units},
          $station->{location}->[0]->{z}->{units};
    }
    for ($i=0;$i<$nloc;$i++) {
      print "$station->{location}->[$i]->{float_year} ",
          "$station->{location}->[$i]->{event}->{name} ",
          "$station->{location}->[$i]->{event}->{type} ",
          "$station->{location}->[$i]->{lon}->{estimate} +- ",
          "$station->{location}->[$i]->{lon}->{uncertainty} ",
          "$station->{location}->[$i]->{lat}->{estimate} +- ",
          "$station->{location}->[$i]->{lat}->{uncertainty} ",
          "$station->{location}->[$i]->{height}->{estimate} +- ",
          "$station->{location}->[$i]->{height}->{uncertainty} ";
       if (defined $station->{location}->[$i]->{Gcorrelation}->{lonlat}) {
         print "$station->{location}->[$i]->{Gcorrelation}->{lonlat} ",
               "$station->{location}->[$i]->{Gcorrelation}->{lonrad} ",
               "$station->{location}->[$i]->{Gcorrelation}->{latrad} ";
       }else{
         print "                             ";
       }
       print "$station->{location}->[$i]->{x}->{estimate} +- ",
             "$station->{location}->[$i]->{x}->{uncertainty} ",
             "$station->{location}->[$i]->{y}->{estimate} +- ",
             "$station->{location}->[$i]->{y}->{uncertainty} ",
             "$station->{location}->[$i]->{z}->{estimate} +- ",
             "$station->{location}->[$i]->{z}->{uncertainty} ";
       if (defined $station->{location}->[$i]->{C_pos_correlation}->{PxPy}) {
         print "$station->{location}->[$i]->{C_pos_correlation}->{PxPy} ",
               "$station->{location}->[$i]->{C_pos_correlation}->{PxPz} ",
               "$station->{location}->[$i]->{C_pos_correlation}->{PyPz} ";
       }
       print "\n";
    }
}

if ($write_velocity) {
  $head1= "#year      event evtype    east_v       v_e_err  north_v       v_n_err  up_v        v_up_err  e-n_cor   e-u_cor  n-u_cor   x            err      y           err        z           err     VxVy                   VxVz                   VyVz                   PxVx                   PxVy                   PxVz                   PyVx                   PyVy                   PyVz                   PzVx                   PzVy                   PzVz";
    if ($use_headers) {
      print "$head1\n";
      printf "#                         %s     %s %s    %s %s  %s                              %s         %s      %s       %s       %s        %s\n",
            $station->{velocity}->[0]->{Veast}->{units},
            $station->{velocity}->[0]->{Veast}->{units},
            $station->{velocity}->[0]->{Vnorth}->{units},
            $station->{velocity}->[0]->{Vnorth}->{units},
            $station->{velocity}->[0]->{Vup}->{units},
            $station->{velocity}->[0]->{Vup}->{units},
            $station->{velocity}->[0]->{Vx}->{units},
            $station->{velocity}->[0]->{Vx}->{units},
            $station->{velocity}->[0]->{Vy}->{units},
            $station->{velocity}->[0]->{Vy}->{units},
            $station->{velocity}->[0]->{Vz}->{units},
            $station->{velocity}->[0]->{Vz}->{units};
    }
    for ($i=0;$i<$nvel;$i++) {
      print "$station->{velocity}->[$i]->{float_year} ",
            "$station->{velocity}->[$i]->{event}->{name} ",
            "$station->{velocity}->[$i]->{event}->{type} ",
            "$station->{velocity}->[$i]->{Veast}->{estimate} +- ",
            "$station->{velocity}->[$i]->{Veast}->{uncertainty} ",
            "$station->{velocity}->[$i]->{Vnorth}->{estimate} +- ",
            "$station->{velocity}->[$i]->{Vnorth}->{uncertainty} ",
            "$station->{velocity}->[$i]->{Vup}->{estimate} +- ",
            "$station->{velocity}->[$i]->{Vup}->{uncertainty} ";
      if (defined $station->{velocity}->[$i]->{Gcorrelation}->{lonlat}) {
        print "$station->{velocity}->[$i]->{Gcorrelation}->{lonlat} ",
              "$station->{velocity}->[$i]->{Gcorrelation}->{lonrad} ",
              "$station->{velocity}->[$i]->{Gcorrelation}->{latrad} ";
      } else {
        print "                             ";
      }
      print "$station->{velocity}->[$i]->{Vx}->{estimate} +- ",
            "$station->{velocity}->[$i]->{Vx}->{uncertainty} ",
            "$station->{velocity}->[$i]->{Vy}->{estimate} +- ",
            "$station->{velocity}->[$i]->{Vy}->{uncertainty} ",
            "$station->{velocity}->[$i]->{Vz}->{estimate} +- ",
            "$station->{velocity}->[$i]->{Vz}->{uncertainty} ";
      if (defined $station->{velocity}->[$i]->{C_vel_correlation}->{VxVy}) {
        print "$station->{velocity}->[$i]->{C_vel_correlation}->{VxVy} ",
              "$station->{velocity}->[$i]->{C_vel_correlation}->{VxVz} ",
              "$station->{velocity}->[$i]->{C_vel_correlation}->{VyVz} ",
              "$station->{velocity}->[$i]->{C_vel_correlation}->{PxVx} ",
              "$station->{velocity}->[$i]->{C_vel_correlation}->{PxVy} ",
              "$station->{velocity}->[$i]->{C_vel_correlation}->{PxVz} ",
              "$station->{velocity}->[$i]->{C_vel_correlation}->{PyVx} ",
              "$station->{velocity}->[$i]->{C_vel_correlation}->{PyVy} ",
              "$station->{velocity}->[$i]->{C_vel_correlation}->{PyVz} ",
              "$station->{velocity}->[$i]->{C_vel_correlation}->{PzVx} ",
              "$station->{velocity}->[$i]->{C_vel_correlation}->{PzVy} ",
              "$station->{velocity}->[$i]->{C_vel_correlation}->{PzVz} ";
       } 
       print  "\n";
    }
}

if ($write_repeat) {
  $head1="#year      event evtype   e_rep   n_rep   u_rep";
    if ($use_headers) {
      print  "$head1\n";
      printf "#                         %s      %s      %s\n",
            $station->{repeatability}->[0]->{rep_east}->{units},
            $station->{repeatability}->[0]->{rep_north}->{units},
            $station->{repeatability}->[0]->{rep_up}->{units};
    }
    for ($i=0;$i<$nrep;$i++) {
      print "$station->{repeatability}->[$i]->{float_year} ",
            "$station->{repeatability}->[$i]->{event}->{name} ",
            "$station->{repeatability}->[$i]->{event}->{type} ",
            "$station->{repeatability}->[$i]->{rep_east}->{content} ",
            "$station->{repeatability}->[$i]->{rep_north}->{content} ",
            "$station->{repeatability}->[$i]->{rep_up}->{content} ",
          "\n";
    }
}

if ($write_fit) {
  print "chi^2 = $station->{fit}->{chi2}\n";
  print "dof = $station->{fit}->{dof}\n";
  print "chi^2/dof = $station->{fit}->{chi2_per_dof}\n";
}

if ($write_series) {
  if ($use_headers) {
    print  "#year     event  evtype      east      e_err       north    n_err      up         u_err             x               x_err                    y                  y_err                  z                  z_err         c_date    ant_ht\n";
    printf "#                            %s        %s          %s       %s         %s         %s              %s              %s              %s                %s              %s                 %s               %s\n",
          $station->{series}->[0]->{east}->{units},
          $station->{series}->[0]->{east}->{units},
          $station->{series}->[0]->{north}->{units},
          $station->{series}->[0]->{north}->{units},
          $station->{series}->[0]->{up}->{units},
          $station->{series}->[0]->{up}->{units},
          $station->{series}->[0]->{x}->{units},
          $station->{series}->[0]->{x}->{units},
          $station->{series}->[0]->{y}->{units},
          $station->{series}->[0]->{y}->{units},
          $station->{series}->[0]->{z}->{units},
          $station->{series}->[0]->{z}->{units},
          $station->{series}->[0]->{ant_height}->{units};
  }
  for ($i=0;$i<$nseries;$i++) {
    print "$station->{series}->[$i]->{float_year} ",
          "$station->{series}->[$i]->{event}->{name} ",
          "$station->{series}->[$i]->{event}->{type} ",
          "$station->{series}->[$i]->{east}->{estimate} +- ",
          "$station->{series}->[$i]->{east}->{uncertainty} ",
          "$station->{series}->[$i]->{north}->{estimate} +- ",
          "$station->{series}->[$i]->{north}->{uncertainty} ",
          "$station->{series}->[$i]->{up}->{estimate} +- ",
          "$station->{series}->[$i]->{up}->{uncertainty} ",
          "$station->{series}->[$i]->{x}->{estimate} +- ",
          "$station->{series}->[$i]->{x}->{uncertainty} ",
          "$station->{series}->[$i]->{y}->{estimate} +- ",
          "$station->{series}->[$i]->{y}->{uncertainty} ",
          "$station->{series}->[$i]->{z}->{estimate} +- ",
          "$station->{series}->[$i]->{z}->{uncertainty} ",
          "$station->{series}->[$i]->{cal_date} ",
          "$station->{series}->[$i]->{ant_height}->{content} ",
        "\n";
  }
}

if ($tmpcomp) {
#  print STDERR "unlinking compressed xml file\n";
  unlink($XMLfname);
}

sub catch_ctlC {
  if ($tmpcomp) {
    unlink($XMLfname);
  }
}
