#!/usr/bin/perl
#======================================================================
# L I S T E N S
# doc: Sat Jan 18 18:41:49 2003
# dlm: Thu Feb 13 10:36:50 2020
# (c) 2003 A.M. Thurnherr
# uE-Info: 96 54 NIL 0 0 72 2 2 4 NIL ofnI
#======================================================================
$synopsis = 'list ensemble summaries (default), dump ensembles (-E), time-average ensembles (-T)';
# HISTORY:
# Jan 18, 2003: - created
# Mar 18, 2004: - updated
# Sep 15, 2005: - made ESW optional (BB150)
# - change RDI binread library name
# Aug 25, 2006: - added -r)ange
# - added write -E)nsembles
# Aug 26, 2006: - added -M)agdecl
# Sep 19, 2007: - adapted to new [RDI_BB_Read.pl] (not tested)
# Jan 26, 2008: - BUG: diagnostic output had been written to STDOUT
# Feb 1, 2008: - BUG: still more diagnostic output written to STDOUT
# - BUG: -E/-A combo had ignored -E
# - changed %-good fieldnames for earth coordinates
# - allowed for 3-beam solutions
# Feb 7, 2008: - added -f)ields
# Apr 4, 2008: - made -f output nan on undefined values
# - BUG: -f fields did not allow array indices
# - added in-w)ater data only
# - restructured for simplicity
# Mar 2, 2009: - added # of valid bin-1 vels to non-ANTS output
# Jul 30, 2009: - NaN => nan
# Aug 15, 2010: - BUG: usage typo
# Dec 10, 2010: - changed ANTS output to time/date instead of UNIX time
# Jan 5, 2011: - added -b
# May 12, 2011: - disabled error exit on built-in-test errors when ensembles are dumped to stdout
# Mar 20, 2013: - removed DATA_FORMAT stuff
# Apr 12, 2013: - added bin number to -E output
# Aug 7, 2013: - added -d, -4
# - added w12, w34 to -E output
# - added sounspeed correction warning
# - changed -E from prefix to suffix
# - added active header line to -E output
# Mar 4, 2014: - added partial support for DATA_SOURCE_ID
# - added support for missing PITCH/ROLL/HEADING
# Sep 8, 2014: - added -B)T
# Mar 17, 2016: - adapted to new Getopt library
# Apr 19, 2016: - added %date, %time to -E output
# Nov 9, 2016: - BUG: no error on missing files
# Feb 7, 2018: - removed 3-beam error
# Apr 1, 2018: - improved usage message
# - removed -Q option (errcheck only, which is not necessary; can use mkProfile to check for errors)
# - added -T (time averaging)
# Apr 2, 2018: - made it work
# - BUG: velBeamToInstrument() was using old usage
# Apr 3, 2018: - BUG: typo
# - added -S from [listBins]
# - removed -B and an BT data (current version did not treat beam-coord BT data correctly)
# Apr 4, 2018: - added support for first_ens and last_ens in [RDI_PD0_IO.pl]
# - removed support for multiple input files
# Apr 10, 2018: - added -l)ast bin
# May 31, 2018: - BUG: -A was disabled by default
# Feb 13, 2020: - added support for $readDataProgress
# Notes:
# - -E/-B outputs data in earth coordinates, unless -b is set also
# - -E/-T output is always in ANTS format
use Getopt::Std;
$ADCP_tools_minVersion = 2.2;
($ADCP_TOOLS) = ($0 =~ m{(.*/)[^/]+});
require "$ADCP_TOOLS/ADCP_tools_lib.pl";
$antsMinLibVersion = 7.0;
($ANTS) = (`which ANTSlib` =~ m{^(.*)/[^/]*$});
require "$ANTS/ants.pl";
require "$ANTS/libconv.pl";
($self) = ($0 =~ m{.*/([^/]+)});
$cmdline = "$self @ARGV";
die("\n$self [-4ABbdEfiMprSTw] <PD0 file> -- $synopsis\n\nCommand-Line Options:\n\t" .
"Output Ensemble Summary (default mode):\n\t\t" .
"[-A)NTS format]\n\t\t" .
"Dump Ensembles (-E|-T; ANTS Format):\n\t\t" .
"[dump individual -E)nsemples <.suff>]\n\t\t" .
"[-T)ime-average ensembles [time-series start (decimal day),]<averaging interval (days)>[,time-series end (decimal day)]]\n\t\t\t" .
"[-i)gnore bins with <fraction> of max samples (-T only)]\n\t\t\t" .
"[output -B)asename <bn>]\n\t\t" .
"[-M)agnetic <declination>]\n\t\t" .
"[-S)oundspeed correction <salin|*,temp|*,depth|*>\n\t\t" .
"[require min -p)ercent-good <#>]\n\t\t" .
"[keep -b)eam coords (do not transform to earth coordinates)]\n\t" .
"Common Options:\n\t\t" .
"[-z print progress dots every 10000 ens\n\t\t" .
"[add -f)ields <[name=]FIELD[,...]>]\n\t\t" .
"[require -4)-beam solutions] [-d)iscard <beam#>]\n\t\t" .
"[-r)ange <first_ens,last_ens>] [-l)ast <bin>]\n\t\t" .
"[in-w)ater ensembles only]\n")
unless (&getopts('4AB:bd:E:f:i:l:M:p:r:S:T:wz') && @ARGV == 1);
die("$ARGV[0]: no such file\n")
unless (-f $ARGV[0]);
$global::readDataProgress = 10000 if defined($opt_z);
$dump_ens = defined($opt_E) + defined($opt_T);
die("$self: cannot combine -E with -T\n") if ($dump_ens > 1);
if (defined($opt_S)) {
($SS_salin,$SS_temp,$SS_depth) = split(',',$opt_S);
} else {
print(STDERR "WARNING: no soundspeed correction applied!\n")
if ($dump_ens);
}
print(STDERR "WARNING: magnetic declination not set!\n")
if ($dump_ens && !defined($opt_M));
die("$self: illegal option combination\n")
if ((defined($opt_M) || defined($opt_p) || defined($opt_b)) && !defined($dump_ens));
die("$self: -4 and -d are mutually exclusive\n")
if ($opt_4 && defined($opt_d));
#undef($opt_A) if defined($dump_ens);
$opt_p = 0 unless defined($opt_p);
if ($opt_f) { # additional fields
@addFields = split(',',$opt_f);
foreach my $f (@addFields) {
$f =~ s/\s//g; # remove spaces
@def = split('=',$f);
if (@def == 2) { # name=field
$addLayout .= $opt_A ? " {$def[0]}" : " $def[0]";
$f = $def[1];
} else { # field
$addLayout .= " {$f}";
}
}
# print(STDERR "addLayout = $addLayout\n");
# print(STDERR "\@addFields = @addFields\n");
}
$RDI_Coords::minValidVels = 4 if ($opt_4); # no 3-beam solutions
#----------------------------------------------------------------------
# MAIN
#----------------------------------------------------------------------
printf(STDERR "Reading $ARGV[0]...");
if (defined($opt_r)) { # read selected range
my($fe,$le) = split(',',$opt_r);
readData(@ARGV,\%dta,$fe,$le,$opt_l);
} else { # read entire file (possibly selected bins)
readData(@ARGV,\%dta,undef,undef,$opt_l);
}
printf(STDERR "\n\t%d complete ensembles\n",scalar(@{$dta{ENSEMBLE}}));
$dta{HEADING_BIAS} = -$opt_M; # magnetic declination
if ($dta{BEAM_COORDINATES}) { # coords used
$beamCoords = 1;
} elsif (!$dta{EARTH_COORDINATES}) {
die("$ARGV[0]: beam or earth coordinates required (implementation restriction)\n");
}
die("$ARGV[0]: -b requires beam-coordinate data\n")
if ($opt_b && !$beamCoords);
($basename) = defined($opt_B) # set basename of output files
? $opt_B
: ($ARGV[0] =~ m{([^\./]+)\.[^\.]+});
#----------------------------------------------------------------------
# define &dumpEns() routine for different output formats:
# -A ANTS format ensemble summary
# -E create one file per ensemble
# -T time-average multiple ensembles
# default: ASCII ensemble summary (human readable)
#----------------------------------------------------------------------
if ($opt_A) { # select output fmt: ANTS
print("#ANTS#PARAMS# PD0_file{$ARGV[0]}\n");
printf("#ANTS#PARAMS# N_ensembles{%d}\n",scalar(@{$dta{ENSEMBLE}}));
print('#ANTS#FIELDS# {ens} {date} {time} {unix-time} {xducer_up} {temp} {hdg} {pitch} {roll} {XMIT_VOLTAGE} {XMIT_CURRENT}');
print(' {ESW}') if ($dta{FIXED_LEADER_BYTES} >= 53);
print("$addLayout\n");
$dumpEns = sub ($)
{
my($e) = @_;
printf('%d %s %s %lf %d %g',
$dta{ENSEMBLE}[$e]->{NUMBER},
$dta{ENSEMBLE}[$e]->{DATE},
$dta{ENSEMBLE}[$e]->{TIME},
$dta{ENSEMBLE}[$e]->{UNIX_TIME},
$dta{ENSEMBLE}[$e]->{XDUCER_FACING_UP} ? 1 : 0,
$dta{ENSEMBLE}[$e]->{TEMPERATURE},
);
if (defined($dta{ENSEMBLE}[$e]->{HEADING})) { printf(' %g',$dta{ENSEMBLE}[$e]->{HEADING}); }
else { printf(' nan'); }
if (defined($dta{ENSEMBLE}[$e]->{PITCH})) { printf(' %g',$dta{ENSEMBLE}[$e]->{PITCH}); }
else { printf(' nan'); }
if (defined($dta{ENSEMBLE}[$e]->{ROLL})) { printf(' %g',$dta{ENSEMBLE}[$e]->{ROLL}); }
else { printf(' nan'); }
printf(' %g %g',
$dta{ENSEMBLE}[$e]->{ADC_XMIT_VOLTAGE},
$dta{ENSEMBLE}[$e]->{ADC_XMIT_CURRENT},
);
printf(' %08X',$dta{ENSEMBLE}[$e]->{ERROR_STATUS_WORD})
if ($dta{FIXED_LEADER_BYTES} >= 53);
foreach my $f (@addFields) {
my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)});
$fn = $f unless defined($fn);
my($v) = eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi");
print(defined($v) ? " $v" : " nan");
}
print("\n");
}
} elsif ($opt_E) { # dump each ensemble in separate file
$dumpEns = sub ($)
{
my($e) = @_;
my($b,$i);
my($file) = "$dta{ENSEMBLE}[$e]->{NUMBER}$opt_E";
my($ssCorr) = defined($opt_S) ? ssCorr($dta{ENSEMBLE}[$e],$SS_salin,$SS_temp,$SS_depth) : 1;
open(P,">$file") || die("$file: $!\n");
print(P "#!/usr/bin/perl -S list\n");
print(P "#ANTS#PARAMS# " .
"date{$dta{ENSEMBLE}[$e]->{DATE}} " .
"time{$dta{ENSEMBLE}[$e]->{TIME}} " .
"soundspeed_correction{%s} " .
"magnetic_declination{%g} " .
"\n",
(defined($opt_S) ? $opt_S : "NONE!"),
$opt_M
);
print(P "#ANTS#FIELDS# " .
"{bin} {dz} {u} {v} {w} {e} {w12} {w34} {corr1} {corr2} {corr3} {corr4} " .
"{amp1} {amp2} {amp3} {amp4} "
);
if ($beamCoords) {
print(P "{pcg1} {pcg2} {pcg3} {pcg4}");
} else {
print(P "{pc3beam} {pcBadErrVel} {pc1or2beam} {pc4beam}");
}
print(P "$addLayout\n");
my($ssCorr) = defined($opt_S) ? ssCorr($dta{ENSEMBLE}[$e],$SS_salin,$SS_temp,$SS_depth) : 1;
for (my($b)=0; $b<$dta{N_BINS}; $b++) {
my(@v,$w12,$w34);
my($dz) = $ssCorr * ($dta{DISTANCE_TO_BIN1_CENTER} + $b*$dta{BIN_LENGTH});
if ($beamCoords) {
undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][0])
if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][0] < $opt_p) || ($opt_d == 1));
undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][1])
if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][1] < $opt_p) || ($opt_d == 2));
undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][2])
if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][2] < $opt_p) || ($opt_d == 3));
undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][3])
if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][3] < $opt_p) || ($opt_d == 4));
($dummy,$w12,$dummy,$w34) =
velBeamToBPEarth(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
@v = $opt_b ? @{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]} :
velBeamToEarth(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
} else {
@v = velApplyHdgBias(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
}
$v[0] *= $ssCorr if defined($v[0]);
$v[1] *= $ssCorr if defined($v[1]);
$v[2] *= $ssCorr if defined($v[2]);
$v[3] *= $ssCorr if defined($v[3]);
$w12 *= $ssCorr if defined($w12);
$w34 *= $ssCorr if defined($w34);
$v[0] = nan unless defined($v[0]); # u
$v[1] = nan unless defined($v[1]); # v
$v[2] = nan unless defined($v[2]); # w
$v[3] = nan unless defined($v[3]); # err_vel
$w12 = nan unless defined($w12); # w from beams 1&2
$w34 = nan unless defined($w34); # w from beams 3&4
my(@out) = (
$b+1,$dz,$v[0],$v[1],$v[2],$v[3],$w12,$w34,
@{$dta{ENSEMBLE}[$e]->{CORRELATION}[$b]},
@{$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b]},
@{$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b]}
);
foreach my $f (@addFields) {
my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)});
$fn = $f unless defined($fn);
push(@out,eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi"));
}
for ($i=0; $i<19+@addFields; $i++) {
$out[$i] = nan unless defined($out[$i]);
}
print(P "@out\n");
}
chmod(0777&~umask,*P);
close(P);
}
} elsif (defined($opt_T)) { # time-average ensembles
my(@tmp) = split(',',$opt_T); # decode -T
my($Tstart,$deltaT,$Tend,$month,$day,$year);
if (@tmp == 3) {
($Tstart,$deltaT,$Tend) = @tmp;
} elsif (@tmp == 2) {
($Tstart,$deltaT) = @tmp;
($month,$day,$year) = split('/',$dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{DATE});
$Tend = str2dec_time($dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{DATE},$dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{TIME},$year);
} else {
($month,$day,$year) = split('/',$dta{ENSEMBLE}[0]->{DATE});
$Tstart = str2dec_time($dta{ENSEMBLE}[0]->{DATE},$dta{ENSEMBLE}[0]->{TIME},$year);
($deltaT) = @tmp;
($month,$day,$year) = split('/',$dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{DATE});
$Tend = str2dec_time($dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{DATE},$dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{TIME},$year);
}
$Tstart = &{&antsCompileConstExpr($')} if ($Tstart =~ m{^=});
$deltaT = &{&antsCompileConstExpr($')} if ($deltaT =~ m{^=});
$Tend = &{&antsCompileConstExpr($')} if ($Tend =~ m{^=});
$deltaT = 9e99 unless ($deltaT > 0);
# format string for zero-padded filenames
my($fnfmt) = sprintf('%%0%dd',length(sprintf('%d',($Tend-$Tstart)/$deltaT+1)));
$cbin = 1; # current tim-bin number; used inside dumpEns
$max_nens = 0; # max number of samples
sub dde($$) # divide allowing for zero; used inside dumpEns
{
my($sum,$n) = @_;
return $n ? $sum/$n : nan;
}
$dumpEns = sub ($) # time average and output when next bin is started
{
my($e) = @_;
my($b,$i);
my($month,$day,$year) = ($e >= 0) ? split('/',$dta{ENSEMBLE}[$e]->{DATE}) : (undef,undef,undef);
my($dn) = ($e >= 0) ? str2dec_time($dta{ENSEMBLE}[$e]->{DATE},$dta{ENSEMBLE}[$e]->{TIME},$year) : undef;
if ($e<0 || $dn>=$Tstart+$cbin*$deltaT) { # dump full bin
my($file) = sprintf("$basename.T$fnfmt",$cbin); # file name: <basename>.T0001
do { # skip empy bins
$cbin++;
} while ($dn>=$Tstart+$cbin*$deltaT);
$max_nens = $a1_n[0] if ($a1_n[0] > $max_nens); # update max number of samples in time bin
if ($a1_n[0] >= $opt_i*$max_nens) { # write file only if sufficient samples (-i)
open(P,">$file") || die("$file: $!\n"); # open file and output metadata
print(P "#!/usr/bin/perl -S list\n");
print(P "#ANTS# $cmdline\n");
printf(P "#ANTS#PARAMS# " .
"PD0_file{$ARGV[0]} " .
"dn{%s} " .
"N_ensembles{%d} ensemble_range{%d,%d} " .
"delta-T{%g} " .
"soundspeed_correction{%s} " .
"magnetic_declination{%g} " .
"\n",
&dde($dn_s,$dn_n),
$a1_n[0],$feib,$leib,$deltaT,
(defined($opt_S) ? $opt_S : "NONE!"),
$opt_M
);
print(P "#ANTS#FIELDS# " . # Layout
"{bin} {dz} {u} {v} {w} {e} {w12} {w34} {corr1} {corr2} {corr3} {corr4} " .
"{amp1} {amp2} {amp3} {amp4} "
);
if ($beamCoords) {
print(P "{pcg1} {pcg2} {pcg3} {pcg4} ");
} else {
print(P "{pc3beam} {pcBadErrVel} {pc1or2beam} {pc4beam} ");
}
print(P "{uvw.nsamp} {e.nsamp} ");
print(P "$addLayout\n");
# ssCorr for dz based on first ensemble in bin
my($ssCorr) = defined($opt_S)
? ssCorr($dta{ENSEMBLE}[$feib-$dta{ENSEMBLE}[0]->{NUMBER}],$SS_salin,$SS_temp,$SS_depth)
: 1;
for (my($b)=0; $b<$dta{N_BINS}; $b++) { # output data
my($dz) = $ssCorr * ($dta{DISTANCE_TO_BIN1_CENTER} + $b*$dta{BIN_LENGTH});
printf(P "%d %g %g %g %g %g %g %g %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
$b+1,$dz,
&dde($v1[$b],$v1_n[$b]),&dde($v2[$b],$v2_n[$b]),&dde($v3[$b],$v3_n[$b]),&dde($v4[$b],$v4_n[$b]),
&dde($w12[$b],$w12_n[$b]),&dde($w34[$b],$w34_n[$b]),
&dde($c1[$b],$c1_n[$b]),&dde($c2[$b],$c2_n[$b]),&dde($c3[$b],$c3_n[$b]),&dde($c4[$b],$c4_n[$b]),
&dde($a1[$b],$a1_n[$b]),&dde($a2[$b],$a2_n[$b]),&dde($a3[$b],$a3_n[$b]),&dde($a4[$b],$a4_n[$b]),
&dde($p1[$b],$p1_n[$b]),&dde($p2[$b],$p2_n[$b]),&dde($p3[$b],$p3_n[$b]),&dde($p4[$b],$p4_n[$b]),
$v1_n[$b],$v4_n[$b]
);
for (my($i)=0; $i<@af; $i++) {
printf(P "%g ",&dde($af[$i][$b],$af_n[$i][$b]));
}
print(P "\n");
}
chmod(0777&~umask,*P); # activate output
close(P);
} # if -i check okay
for (my($b)=0; $b<$dta{N_BINS}; $b++) { # reset stats
$v1[$b] = $v1_n[$b] = $v2[$b] = $v2_n[$b] = $v3[$b] = $v3_n[$b] = $v4[$b] = $v4_n[$b] = 0;
$w12[$b] = $w12_n[$b] = $w34[$b] = $w34_n[$b] = 0;
$c1[$b] = $c1_n[$b] = $c2[$b] = $c2_n[$b] = $c3[$b] = $c3_n[$b] = $c4[$b] = $c4_n[$b] = 0;
$a1[$b] = $a1_n[$b] = $a2[$b] = $a2_n[$b] = $a3[$b] = $a3_n[$b] = $a4[$b] = $a4_n[$b] = 0;
$p1[$b] = $p1_n[$b] = $p2[$b] = $p2_n[$b] = $p3[$b] = $p3_n[$b] = $p4[$b] = $p4_n[$b] = 0;
for (my($i)=0; $i<@af; $i++) {
$af[$i][$b] = $af_n[$i][$b] = 0;
}
$dn_s = $dn_n = 0; # day number
}
undef($feib); # make sure first ensemble in bin will be updated below
} # if time bin is full
$feib = $dta{ENSEMBLE}[$e]->{NUMBER} unless defined($feib); # update first and last ensembles in current bin
$leib = $dta{ENSEMBLE}[$e]->{NUMBER};
$dn_s += $dn; $dn_n++; # day number
my($ssCorr) = defined($opt_S) ? ssCorr($dta{ENSEMBLE}[$e],$SS_salin,$SS_temp,$SS_depth) : 1;
for (my($b)=0; $b<$dta{N_BINS}; $b++) {
my(@v,$this_w12,$this_w34);
if ($beamCoords) { # convert to earth coordinates
undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][0])
if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][0] < $opt_p) || ($opt_d == 1));
undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][1])
if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][1] < $opt_p) || ($opt_d == 2));
undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][2])
if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][2] < $opt_p) || ($opt_d == 3));
undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][3])
if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][3] < $opt_p) || ($opt_d == 4));
($dummy,$this_w12,$dummy,$this_w34) =
velBeamToBPEarth(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
@v = $opt_b ? @{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]} :
velBeamToEarth(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
} else {
@v = velApplyHdgBias(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
}
$v[0] *= $ssCorr if defined($v[0]); $v[1] *= $ssCorr if defined($v[1]); # apply sound-speed correction
$v[2] *= $ssCorr if defined($v[2]); $v[3] *= $ssCorr if defined($v[3]);
$w12 *= $ssCorr if defined($w12); $w34 *= $ssCorr if defined($w34);
$v1[$b]+=$v[0],$v1_n[$b]++ if defined($v[0]); # update sums and nsamps
$v2[$b]+=$v[1],$v2_n[$b]++ if defined($v[1]);
$v3[$b]+=$v[2],$v3_n[$b]++ if defined($v[2]);
$v4[$b]+=$v[3],$v4_n[$b]++ if defined($v[3]);
$w12[$b]+=$this_w12,$w12_n[$b]++ if defined($this_w12);
$w34[$b]+=$this_w34,$w34_n[$b]++ if defined($this_w34);
$c1[$b]+=$dta{ENSEMBLE}[$e]->{CORRELATION}[$b][0],$c1_n[$b]++;
$c2[$b]+=$dta{ENSEMBLE}[$e]->{CORRELATION}[$b][1],$c2_n[$b]++;
$c3[$b]+=$dta{ENSEMBLE}[$e]->{CORRELATION}[$b][2],$c3_n[$b]++;
$c4[$b]+=$dta{ENSEMBLE}[$e]->{CORRELATION}[$b][3],$c4_n[$b]++;
$a1[$b]+=$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b][0],$a1_n[$b]++;
$a2[$b]+=$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b][1],$a2_n[$b]++;
$a3[$b]+=$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b][2],$a3_n[$b]++;
$a4[$b]+=$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b][3],$a4_n[$b]++;
$p1[$b]+=$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][0],$p1_n[$b]++;
$p2[$b]+=$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][1],$p2_n[$b]++;
$p3[$b]+=$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][2],$p3_n[$b]++;
$p4[$b]+=$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][3],$p4_n[$b]++;
my($fi) = 0;
foreach my $f (@addFields) {
my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)});
$fn = $f unless defined($fn);
my($val) = eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi");
$af[$fi][$b]+=$val,$af_n[$fi][$b]++ if defined($val);
$fi++;
}
}
}
} else { # neither ANTS nor ens files (DEFAULT OUTPUT)
if ($dta{FIXED_LEADER_BYTES} >= 53) {
printf("Ens # Date Time XD Temp Headng Pitch Roll #vv DSID ESW$addLayout\n");
printf("----------------------------------------------------------------------------\n");
} else {
printf("Ens # Date Time XD Temp Headng Pitch Roll #vv DSID$addLayout\n");
printf("------------------------------------------------------------------------\n");
}
$dumpEns = sub ($)
{
my($e) = @_;
printf('%5d %s %s %s %5.1f',
$dta{ENSEMBLE}[$e]->{NUMBER},
$dta{ENSEMBLE}[$e]->{DATE},
$dta{ENSEMBLE}[$e]->{TIME},
$dta{ENSEMBLE}[$e]->{XDUCER_FACING_UP} ? "UP" : "DN",
$dta{ENSEMBLE}[$e]->{TEMPERATURE},
);
if (defined($dta{ENSEMBLE}[$e]->{HEADING})) { printf(' %6.1f',$dta{ENSEMBLE}[$e]->{HEADING}); }
else { printf(' nan'); }
if (defined($dta{ENSEMBLE}[$e]->{PITCH})) { printf(' %5.1f',$dta{ENSEMBLE}[$e]->{PITCH}); }
else { printf(' nan'); }
if (defined($dta{ENSEMBLE}[$e]->{ROLL})) { printf(' %5.1f',$dta{ENSEMBLE}[$e]->{ROLL}); }
else { printf(' nan'); }
printf(' %3d 0x%02X',
$dta{ENSEMBLE}[$e]->{BIN1VELS},
$dta{ENSEMBLE}[$e]->{DATA_SOURCE_ID},
);
printf(' 0x%08X',$dta{ENSEMBLE}[$e]->{ERROR_STATUS_WORD})
if ($dta{FIXED_LEADER_BYTES} >= 53);
foreach my $f (@addFields) {
my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)});
$fn = $f unless defined($fn);
my($v) = eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi");
print(defined($v) ? " $v" : " nan");
}
print(" BUILT-IN-TEST ERROR")
if defined($dta{ENSEMBLE}[$e]->{BUILT_IN_TEST_ERROR});
print("\n");
}
} # define output format
#----------------------------------------------------------------------
# Loop Over Ensembles
#----------------------------------------------------------------------
for ($e=0; $e<=$#{$dta{ENSEMBLE}}; $e++) {
$dta{ENSEMBLE}[$e]->{BIN1VELS} =
defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][0]) +
defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][1]) +
defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][2]) +
defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][3]);
next if ($opt_w && $dta{ENSEMBLE}[$e]->{BIN1VELS}<3);
die("BIT error in ensemble $dta{ENSEMBLE}[$e]->{NUMBER}\n")
if ($opt_A || $dump_ens) && defined($dta{ENSEMBLE}[$e]->{BUILT_IN_TEST_ERROR});
die("Low gain in ensemble #$dta{ENSEMBLE}[$e]->{NUMBER}\n")
if ($dta{ENSEMBLE}[$e]->{LOW_GAIN});
&$dumpEns($e);
}
&$dumpEns(-1) if defined($opt_T); # dump final bin
exit(0);