listEns
changeset 43 b63fa355644c
parent 37 40d85448debf
child 50 6bfec705d25e
equal deleted inserted replaced
42:80d039881d2c 43:b63fa355644c
     1 #!/usr/bin/perl
     1 #!/usr/bin/perl
     2 #======================================================================
     2 #======================================================================
     3 #                    L I S T E N S 
     3 #                    L I S T E N S 
     4 #                    doc: Sat Jan 18 18:41:49 2003
     4 #                    doc: Sat Jan 18 18:41:49 2003
     5 #                    dlm: Wed Nov  9 12:27:32 2016
     5 #                    dlm: Thu May 31 11:10:51 2018
     6 #                    (c) 2003 A.M. Thurnherr
     6 #                    (c) 2003 A.M. Thurnherr
     7 #                    uE-Info: 115 0 NIL 0 0 72 2 2 4 NIL ofnI
     7 #                    uE-Info: 62 51 NIL 0 0 72 2 2 4 NIL ofnI
     8 #======================================================================
     8 #======================================================================
     9 
     9 
    10 # Print useful info from the ensemble list or dump ensembles to
    10 $synopsis = 'list ensemble summaries (default), dump ensembles (-E), time-average ensembles (-T)';
    11 # separate files.
       
    12 
    11 
    13 # HISTORY:
    12 # HISTORY:
    14 #	Jan 18, 2003: - created
    13 #	Jan 18, 2003: - created
    15 #	Mar 18, 2004: - updated
    14 #	Mar 18, 2004: - updated
    16 #	Sep 15, 2005: - made ESW optional (BB150)
    15 #	Sep 15, 2005: - made ESW optional (BB150)
    46 #				  - added support for missing PITCH/ROLL/HEADING
    45 #				  - added support for missing PITCH/ROLL/HEADING
    47 #	Sep  8, 2014: - added -B)T  
    46 #	Sep  8, 2014: - added -B)T  
    48 #   Mar 17, 2016: - adapted to new Getopt library
    47 #   Mar 17, 2016: - adapted to new Getopt library
    49 #	Apr 19, 2016: - added %date, %time to -E output
    48 #	Apr 19, 2016: - added %date, %time to -E output
    50 #	Nov  9, 2016: - BUG: no error on missing files
    49 #	Nov  9, 2016: - BUG: no error on missing files
       
    50 #	Feb  7, 2018: - removed 3-beam error
       
    51 #	Apr  1, 2018: - improved usage message
       
    52 #				  - removed -Q option (errcheck only, which is not necessary; can use mkProfile to check for errors)
       
    53 #				  - added -T (time averaging)
       
    54 #	Apr  2, 2018: - made it work
       
    55 #				  - BUG: velBeamToInstrument() was using old usage
       
    56 #	Apr  3, 2018: - BUG: typo
       
    57 #				  - added -S from [listBins]
       
    58 #				  - removed -B and an BT data (current version did not treat beam-coord BT data correctly)
       
    59 #	Apr  4, 2018: - added support for first_ens and last_ens in [RDI_PD0_IO.pl]
       
    60 #				  - removed support for multiple input files
       
    61 #	Apr 10, 2018: - added -l)ast bin
       
    62 #	May 31, 2018: - BUG: -A was disabled by default
    51 
    63 
    52 # Notes:
    64 # Notes:
    53 #	- -E outputs data in earth coordinates, unless -b is set also
    65 #	- -E/-B outputs data in earth coordinates, unless -b is set also
    54 #	- -E output is always in ANTS format, ignoring -A
    66 #	- -E/-T output is always in ANTS format
    55 #	- no soundspeed correction
       
    56 
    67 
    57 use Getopt::Std;
    68 use Getopt::Std;
    58 $0 =~ m{(.*/)[^/]+};
    69 
    59 require "$1RDI_BB_Read.pl";
    70 $ADCP_tools_minVersion = 2.2;
    60 require "$1RDI_Coords.pl";
    71 ($ADCP_TOOLS) = ($0 =~ m{(.*/)[^/]+});
    61 
    72 require "$ADCP_TOOLS/ADCP_tools_lib.pl";
    62 die("Usage: $0 [-A)nts] [-Q)uiet (errcheck only)] " .
    73 
    63 			  "[-f)ields <[name=]FIELD[,...]>] " .
    74 $antsMinLibVersion = 7.0;
    64 			  "[require -4)-beam solutions] [-d)iscard <beam#>] " .
    75 ($ANTS) = (`which ANTSlib` =~ m{^(.*)/[^/]*$});
    65 			  "[write -E)nsemples <.suff> [use -B)T] [-M)agnetic <declination>] [min -p)ercent-good <#>] [keep -b)eam coords]] " .
    76 require "$ANTS/ants.pl";
    66 			  "[-r)ange <first_ens,last_ens>] [in-w)ater ensembles only] " .
    77 require "$ANTS/libconv.pl";
    67 			  "<RDI file...>\n")
    78 
    68 	unless (&getopts("4ABbd:E:f:M:p:Qr:w") && $#ARGV >= 0);
    79 ($self) = ($0 =~ m{.*/([^/]+)});
    69 
    80 $cmdline = "$self @ARGV";
    70 print(STDERR "WARNING: no soundspeed correction applied!\n");
    81 
       
    82 die("\n$self [-4ABbdEfiMprSTw] <PD0 file> -- $synopsis\n\nCommand-Line Options:\n\t" .
       
    83 			  "Output Ensemble Summary (default mode):\n\t\t" .
       
    84 				  "[-A)NTS format]\n\t\t" .
       
    85 			  "Dump Ensembles (-E|-T; ANTS Format):\n\t\t" .
       
    86 				  "[dump individual -E)nsemples <.suff>]\n\t\t" .
       
    87 				  "[-T)ime-average ensembles [time-series start (decimal day),]<averaging interval (days)>[,time-series end (decimal day)]]\n\t\t\t" .
       
    88 				  	"[-i)gnore bins with <fraction> of max samples (-T only)]\n\t\t\t" .
       
    89 				  	"[output -B)asename <bn>]\n\t\t" .
       
    90 				  "[-M)agnetic <declination>]\n\t\t" .
       
    91 				  "[-S)oundspeed correction <salin|*,temp|*,depth|*>\n\t\t" .
       
    92 				  "[require min -p)ercent-good <#>]\n\t\t" .
       
    93 				  "[keep -b)eam coords (do not transform to earth coordinates)]\n\t" .
       
    94 			  "Common Options:\n\t\t" .
       
    95 				  "[add -f)ields <[name=]FIELD[,...]>]\n\t\t" .
       
    96 				  "[require -4)-beam solutions] [-d)iscard <beam#>]\n\t\t" .
       
    97 				  "[-r)ange <first_ens,last_ens>] [-l)ast <bin>]\n\t\t" .
       
    98 				  "[in-w)ater ensembles only]\n")
       
    99 	unless (&getopts("4AB:bd:E:f:i:l:M:p:r:S:T:w") && @ARGV == 1);
       
   100 
       
   101 die("$ARGV[0]: no such file\n")
       
   102 	unless (-f $ARGV[0]);
       
   103 
       
   104 $dump_ens = defined($opt_E) + defined($opt_T);
       
   105 die("$self: cannot combine -E with -T\n") if ($dump_ens > 1);
       
   106 
       
   107 if (defined($opt_S)) {
       
   108 	($SS_salin,$SS_temp,$SS_depth) = split(',',$opt_S);
       
   109 } else {
       
   110 	print(STDERR "WARNING: no soundspeed correction applied!\n")
       
   111 		if ($dump_ens);
       
   112 }
    71 
   113 
    72 print(STDERR "WARNING: magnetic declination not set!\n")
   114 print(STDERR "WARNING: magnetic declination not set!\n")
    73 	if defined($opt_E) && !defined($opt_M);
   115 	if ($dump_ens && !defined($opt_M));
    74 
   116 
    75 die("$0: illegal option combination\n")
   117 die("$self: illegal option combination\n")
    76 	if ($opt_Q && $opt_A) || ((defined($opt_M) || defined($opt_p) || defined($opt_b) || $opt_B) && !defined($opt_E));
   118 	if ((defined($opt_M) || defined($opt_p) || defined($opt_b)) && !defined($dump_ens));
    77 
   119 
    78 die("$0: -4 and -d are mutually exclusive\n")
   120 die("$self: -4 and -d are mutually exclusive\n")
    79 	if ($opt_4 && defined($opt_d));
   121 	if ($opt_4 && defined($opt_d));
    80 
   122 
    81 ($first_ens,$last_ens) = split(',',$opt_r)
   123 #undef($opt_A) if defined($dump_ens);
    82 	if defined($opt_r);
       
    83 
       
    84 undef($opt_A) if defined($opt_E);
       
    85 
   124 
    86 $opt_p = 0 unless defined($opt_p);
   125 $opt_p = 0 unless defined($opt_p);
    87 
   126 
    88 if ($opt_f) {										# additional fields
   127 if ($opt_f) {										# additional fields
    89 	@addFields = split(',',$opt_f);
   128 	@addFields = split(',',$opt_f);
   105 
   144 
   106 #----------------------------------------------------------------------
   145 #----------------------------------------------------------------------
   107 # MAIN
   146 # MAIN
   108 #----------------------------------------------------------------------
   147 #----------------------------------------------------------------------
   109 
   148 
   110 while ($ARGV[0] ne '') {
   149 printf(STDERR "Reading $ARGV[0]...");
   111 	die("$ARGV[0]: No such file or directory\n")
   150 if (defined($opt_r)) {								# read selected range
   112 		unless (-f $ARGV[0]);
   151 	my($fe,$le) = split(',',$opt_r);
   113 
   152 	readData(@ARGV,\%dta,$fe,$le,$opt_l);
   114 	readData(@ARGV,\%dta);
   153 } else {											# read entire file (possibly selected bins)
   115 	if ($opt_A && !$opt_E) {
   154 	readData(@ARGV,\%dta,undef,undef,$opt_l);
   116 		print("#ANTS#PARAMS# RDI_file{$ARGV[0]}\n");
   155 }
   117 	} elsif (!$opt_Q) {
   156 printf(STDERR "\n\t%d complete ensembles\n",scalar(@{$dta{ENSEMBLE}}));
   118 		print(STDERR "$ARGV[0]: ");
   157 
   119 	}
   158 $dta{HEADING_BIAS} = -$opt_M;						# magnetic declination
   120 	printf(STDERR "%d complete ensembles...\n",scalar(@{$dta{ENSEMBLE}}))
   159 
   121 		unless ($opt_Q);
   160 if ($dta{BEAM_COORDINATES}) {						# coords used
   122 	$dta{HEADING_BIAS} = -$opt_M;						# magnetic declination
   161 	$beamCoords = 1;
   123 	shift;
   162 } elsif (!$dta{EARTH_COORDINATES}) {
   124 
   163 	die("$ARGV[0]: beam or earth coordinates required (implementation restriction)\n");
   125 	if ($dta{BEAM_COORDINATES}) {						# coords used
   164 }
   126 		$beamCoords = 1;
   165 die("$ARGV[0]: -b requires beam-coordinate data\n")
   127 	} elsif (!$dta{EARTH_COORDINATES}) {
   166 	if ($opt_b && !$beamCoords);
   128 		die("$ARGV[0]: only beam and earth coordinates implemented so far\n");
   167 
   129 	}
   168 ($basename) = defined($opt_B)						# set basename of output files
   130 
   169 			? $opt_B
   131 	die("$ARGV[0]: -b only makes sense for beam-coordinate data\n")
   170 			: ($ARGV[0] =~ m{([^\./]+)\.[^\.]+});
   132 		if ($opt_b && !$beamCoords);
   171 
   133 
   172 #----------------------------------------------------------------------
   134 	if ($opt_A) {										# select output fmt: ANTS
   173 # define &dumpEns() routine for different output formats:
   135 		unless ($opt_Q) {
   174 #	-A			ANTS format ensemble summary
   136 			printf("#ANTS#PARAMS# N_ensembles{%d}\n",scalar(@{$dta{ENSEMBLE}}));
   175 #	-E			create one file per ensemble
   137 			print('#ANTS#FIELDS# {ens} {time} {xducer_up} {temp} {hdg} {pitch} {roll} {XMIT_VOLTAGE} {XMIT_CURRENT}');
   176 #	-T			time-average multiple ensembles
   138 			print(' {ESW}') if ($dta{FIXED_LEADER_BYTES} >= 53);
   177 #	default:	ASCII ensemble summary (human readable)
   139 	        print("$addLayout\n");
   178 #----------------------------------------------------------------------
   140 	    }
   179 
   141 
   180 if ($opt_A) {										# select output fmt: ANTS
   142 		$dumpEns = sub ($)
   181 	print("#ANTS#PARAMS# PD0_file{$ARGV[0]}\n");
   143 		{
   182 	printf("#ANTS#PARAMS# N_ensembles{%d}\n",scalar(@{$dta{ENSEMBLE}}));
   144 			my($e) = @_;
   183 	print('#ANTS#FIELDS# {ens} {date} {time} {unix-time} {xducer_up} {temp} {hdg} {pitch} {roll} {XMIT_VOLTAGE} {XMIT_CURRENT}');
   145 			
   184 	print(' {ESW}') if ($dta{FIXED_LEADER_BYTES} >= 53);
   146 			printf('%d %lf %d %g',
   185 	print("$addLayout\n");
   147 				$dta{ENSEMBLE}[$e]->{NUMBER},
   186 
   148 				$dta{ENSEMBLE}[$e]->{UNIX_TIME},
   187 	$dumpEns = sub ($)
   149 				$dta{ENSEMBLE}[$e]->{XDUCER_FACING_UP} ? 1 : 0,
   188 	{
   150 				$dta{ENSEMBLE}[$e]->{TEMPERATURE},
   189 		my($e) = @_;
       
   190 	    
       
   191 		printf('%d %s %s %lf %d %g',
       
   192 			$dta{ENSEMBLE}[$e]->{NUMBER},
       
   193 			$dta{ENSEMBLE}[$e]->{DATE},
       
   194 			$dta{ENSEMBLE}[$e]->{TIME},
       
   195 			$dta{ENSEMBLE}[$e]->{UNIX_TIME},
       
   196 			$dta{ENSEMBLE}[$e]->{XDUCER_FACING_UP} ? 1 : 0,
       
   197 			$dta{ENSEMBLE}[$e]->{TEMPERATURE},
       
   198 		);
       
   199 		if (defined($dta{ENSEMBLE}[$e]->{HEADING})) { printf(' %g',$dta{ENSEMBLE}[$e]->{HEADING}); }
       
   200 		else { printf(' nan'); }
       
   201 		if (defined($dta{ENSEMBLE}[$e]->{PITCH})) { printf(' %g',$dta{ENSEMBLE}[$e]->{PITCH}); }
       
   202 		else { printf(' nan'); }
       
   203 		if (defined($dta{ENSEMBLE}[$e]->{ROLL})) { printf(' %g',$dta{ENSEMBLE}[$e]->{ROLL}); }
       
   204 		else { printf(' nan'); }
       
   205 		printf(' %g %g',
       
   206 			$dta{ENSEMBLE}[$e]->{ADC_XMIT_VOLTAGE},
       
   207 			$dta{ENSEMBLE}[$e]->{ADC_XMIT_CURRENT},
       
   208 		);
       
   209 		printf(' %08X',$dta{ENSEMBLE}[$e]->{ERROR_STATUS_WORD})
       
   210 			if ($dta{FIXED_LEADER_BYTES} >= 53);
       
   211 		foreach my $f (@addFields) {
       
   212 			my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)});
       
   213 			$fn = $f unless defined($fn);
       
   214 			my($v) = eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi");
       
   215 			print(defined($v) ? " $v" : " nan");
       
   216 		}
       
   217 		print("\n");
       
   218 	}
       
   219 
       
   220 } elsif ($opt_E) {										# dump each ensemble in separate file 
       
   221 
       
   222 	$dumpEns = sub ($)
       
   223 	{
       
   224 		my($e) = @_;
       
   225 		my($b,$i);
       
   226 		my($file) = "$dta{ENSEMBLE}[$e]->{NUMBER}$opt_E";
       
   227     
       
   228 		my($ssCorr) = defined($opt_S) ? ssCorr($dta{ENSEMBLE}[$e],$SS_salin,$SS_temp,$SS_depth) : 1;
       
   229 
       
   230 		open(P,">$file") || die("$file: $!\n");
       
   231 		print(P "#!/usr/bin/perl -S list\n");
       
   232 		print(P "#ANTS#PARAMS# " .
       
   233 				"date{$dta{ENSEMBLE}[$e]->{DATE}} " .
       
   234 				"time{$dta{ENSEMBLE}[$e]->{TIME}} " .
       
   235 				"soundspeed_correction{%s} " .
       
   236 				"magnetic_declination{%g} " .
       
   237 				"\n",
       
   238 					(defined($opt_S) ? $opt_S : "NONE!"),
       
   239 					$opt_M
       
   240 		);
       
   241 		print(P "#ANTS#FIELDS# " .
       
   242 				"{bin} {dz} {u} {v} {w} {e} {w12} {w34} {corr1} {corr2} {corr3} {corr4} " .
       
   243 				"{amp1} {amp2} {amp3} {amp4} "
       
   244 		);
       
   245 		if ($beamCoords) {
       
   246 			print(P "{pcg1} {pcg2} {pcg3} {pcg4}");
       
   247 		} else {
       
   248 			print(P "{pc3beam} {pcBadErrVel} {pc1or2beam} {pc4beam}");
       
   249 		}
       
   250 		print(P "$addLayout\n");
       
   251 		    
       
   252 		my($ssCorr) = defined($opt_S) ? ssCorr($dta{ENSEMBLE}[$e],$SS_salin,$SS_temp,$SS_depth) : 1;
       
   253 		for (my($b)=0; $b<$dta{N_BINS}; $b++) {
       
   254 			my(@v,$w12,$w34);
       
   255 			my($dz) = $ssCorr * ($dta{DISTANCE_TO_BIN1_CENTER} + $b*$dta{BIN_LENGTH});
       
   256     
       
   257 			if ($beamCoords) {
       
   258 				undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][0])
       
   259 					if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][0] < $opt_p) || ($opt_d == 1));
       
   260 				undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][1])
       
   261 					if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][1] < $opt_p) || ($opt_d == 2));
       
   262 				undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][2])
       
   263 					if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][2] < $opt_p) || ($opt_d == 3));
       
   264 				undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][3])
       
   265 					if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][3] < $opt_p) || ($opt_d == 4));
       
   266 				($dummy,$w12,$dummy,$w34) =
       
   267 					velBeamToBPEarth(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
       
   268 				@v = $opt_b ? @{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]} :
       
   269 							  velBeamToEarth(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
       
   270 			} else {
       
   271 				@v = velApplyHdgBias(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
       
   272 			}
       
   273 			$v[0] *= $ssCorr if defined($v[0]);
       
   274 			$v[1] *= $ssCorr if defined($v[1]);
       
   275 			$v[2] *= $ssCorr if defined($v[2]);
       
   276 			$v[3] *= $ssCorr if defined($v[3]);
       
   277 			$w12 *= $ssCorr if defined($w12);
       
   278 			$w34 *= $ssCorr if defined($w34);
       
   279     
       
   280 			$v[0] = nan unless defined($v[0]);		# u
       
   281 			$v[1] = nan unless defined($v[1]);		# v
       
   282 			$v[2] = nan unless defined($v[2]);		# w
       
   283 			$v[3] = nan unless defined($v[3]);		# err_vel
       
   284 			$w12 = nan unless defined($w12);		# w from beams 1&2
       
   285 			$w34 = nan unless defined($w34);		# w from beams 3&4
       
   286 
       
   287 			my(@out) = (
       
   288 				$b+1,$dz,$v[0],$v[1],$v[2],$v[3],$w12,$w34,
       
   289 				@{$dta{ENSEMBLE}[$e]->{CORRELATION}[$b]},
       
   290 				@{$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b]},
       
   291 				@{$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b]}
   151 			);
   292 			);
   152 			if (defined($dta{ENSEMBLE}[$e]->{HEADING})) { printf(' %g',$dta{ENSEMBLE}[$e]->{HEADING}); }
       
   153 			else { printf(' nan'); }
       
   154 			if (defined($dta{ENSEMBLE}[$e]->{PITCH})) { printf(' %g',$dta{ENSEMBLE}[$e]->{PITCH}); }
       
   155 			else { printf(' nan'); }
       
   156 			if (defined($dta{ENSEMBLE}[$e]->{ROLL})) { printf(' %g',$dta{ENSEMBLE}[$e]->{ROLL}); }
       
   157 			else { printf(' nan'); }
       
   158 			printf(' %g %g',
       
   159 				$dta{ENSEMBLE}[$e]->{ADC_XMIT_VOLTAGE},
       
   160 				$dta{ENSEMBLE}[$e]->{ADC_XMIT_CURRENT},
       
   161 			);
       
   162 			printf(' %08X',$dta{ENSEMBLE}[$e]->{ERROR_STATUS_WORD})
       
   163 				if ($dta{FIXED_LEADER_BYTES} >= 53);
       
   164 			foreach my $f (@addFields) {
   293 			foreach my $f (@addFields) {
   165 				my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)});
   294 				my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)});
   166 				$fn = $f unless defined($fn);
   295 				$fn = $f unless defined($fn);
   167 				my($v) = eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi");
   296 				push(@out,eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi"));
   168 				print(defined($v) ? " $v" : " nan");
       
   169 			}
   297 			}
   170 			print("\n");
   298 			for ($i=0; $i<19+@addFields; $i++) {
       
   299 				$out[$i] = nan unless defined($out[$i]);
       
   300 			}
       
   301 			print(P "@out\n");
   171 		}
   302 		}
   172 
   303 		chmod(0777&~umask,*P);
   173 	} elsif ($opt_E) {										# one file per ens
   304 		close(P);
   174 
   305 	}
   175 		$dumpEns = sub ($)
   306 
   176 		{
   307 } elsif (defined($opt_T)) { 									# time-average ensembles
   177 			my($e) = @_;
   308 
   178 			my($b,$i);
   309 	my(@tmp) = split(',',$opt_T);								# decode -T 
   179 			my($file) = "$dta{ENSEMBLE}[$e]->{NUMBER}$opt_E";
   310 	my($Tstart,$deltaT,$Tend,$month,$day,$year);
   180 		
   311 	if (@tmp == 3) {
   181 			open(P,">$file") || die("$file: $!\n");
   312 		($Tstart,$deltaT,$Tend) = @tmp;
   182 			print(P "#!/usr/bin/perl -S list\n");
   313 	} elsif (@tmp == 2) {
   183 			print(P "#ANTS#PARAMS# " .
   314 		($Tstart,$deltaT) = @tmp;
   184 					"date{$dta{ENSEMBLE}[$e]->{DATE}} " .
   315 		($month,$day,$year) = split('/',$dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{DATE});
   185 					"time{$dta{ENSEMBLE}[$e]->{TIME}} " .
   316 		$Tend = str2dec_time($dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{DATE},$dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{TIME},$year);
   186 					"BT_u{$dta{ENSEMBLE}[$e]->{BT_VELOCITY}[0]} " .
   317 	} else {
   187 					"BT_v{$dta{ENSEMBLE}[$e]->{BT_VELOCITY}[1]} " .
   318 		($month,$day,$year) = split('/',$dta{ENSEMBLE}[0]->{DATE});
   188 					"BT_w{$dta{ENSEMBLE}[$e]->{BT_VELOCITY}[2]} " .
   319 		$Tstart = str2dec_time($dta{ENSEMBLE}[0]->{DATE},$dta{ENSEMBLE}[0]->{TIME},$year);
   189 					"BT_e{$dta{ENSEMBLE}[$e]->{BT_VELOCITY}[3]} " .
   320 		($deltaT) = @tmp;
   190 					"BT_cor1{$dta{ENSEMBLE}[$e]->{BT_CORRELATION}[0]} " .
   321 		($month,$day,$year) = split('/',$dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{DATE});
   191 					"BT_cor2{$dta{ENSEMBLE}[$e]->{BT_CORRELATION}[1]} " .
   322 		$Tend = str2dec_time($dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{DATE},$dta{ENSEMBLE}[$#{$dta{ENSEMBLE}}]->{TIME},$year);
   192 					"BT_cor3{$dta{ENSEMBLE}[$e]->{BT_CORRELATION}[2]} " .
   323 	}
   193 					"BT_cor4{$dta{ENSEMBLE}[$e]->{BT_CORRELATION}[3]} " .
   324 	$Tstart = &{&antsCompileConstExpr($')} if ($Tstart =~ m{^=});
   194 					"BT_amp1{$dta{ENSEMBLE}[$e]->{BT_AMPLITUDE}[0]} " .
   325 	$deltaT = &{&antsCompileConstExpr($')} if ($deltaT =~ m{^=});
   195 					"BT_amp2{$dta{ENSEMBLE}[$e]->{BT_AMPLITUDE}[1]} " .
   326 	$Tend	= &{&antsCompileConstExpr($')} if ($Tend   =~ m{^=});
   196 					"BT_amp3{$dta{ENSEMBLE}[$e]->{BT_AMPLITUDE}[2]} " .
   327 	$deltaT = 9e99 unless ($deltaT > 0);
   197 					"BT_amp4{$dta{ENSEMBLE}[$e]->{BT_AMPLITUDE}[3]} " .
   328 																# format string for zero-padded filenames
   198 					"soundspeed_correction{NONE!} " .
   329 	my($fnfmt) = sprintf('%%0%dd',length(sprintf('%d',($Tend-$Tstart)/$deltaT+1)));
   199 					"\n"
   330 
   200 			);
   331 	$cbin		= 1;											# current tim-bin number; used inside dumpEns
   201 			print(P "#ANTS#FIELDS# " .
   332 	$max_nens	= 0;											# max number of samples
   202 					"{bin} {dz} {u} {v} {w} {e} {w12} {w34} {cor1} {cor2} {cor3} {cor4} " .
   333 
   203 					"{amp1} {amp2} {amp3} {amp4} "
   334 	sub dde($$) 												# divide allowing for zero; used inside dumpEns
   204 			);
   335 	{
   205 			if ($beamCoords) {
   336 		my($sum,$n) = @_;
   206 				print(P "{pcg1} {pcg2} {pcg3} {pcg4}");
   337 		return $n ? $sum/$n : nan;
       
   338 	}
       
   339 
       
   340 	$dumpEns = sub ($)											# time average and output when next bin is started
       
   341 	{
       
   342 		my($e) = @_;
       
   343 		my($b,$i);
       
   344 
       
   345 		my($month,$day,$year) = ($e >= 0) ? split('/',$dta{ENSEMBLE}[$e]->{DATE}) : (undef,undef,undef);
       
   346 		my($dn) = ($e >= 0) ? str2dec_time($dta{ENSEMBLE}[$e]->{DATE},$dta{ENSEMBLE}[$e]->{TIME},$year) : undef;
       
   347 
       
   348 		if ($e<0 || $dn>=$Tstart+$cbin*$deltaT) {				# dump full bin
       
   349 			my($file) = sprintf("$basename.T$fnfmt",$cbin); 	# file name: <basename>.T0001
       
   350 
       
   351 			do {												# skip empy bins
       
   352 				$cbin++;
       
   353 			} while ($dn>=$Tstart+$cbin*$deltaT);
       
   354 
       
   355 			$max_nens = $a1_n[0] if ($a1_n[0] > $max_nens); 	# update max number of samples in time bin
       
   356 			if ($a1_n[0] >= $opt_i*$max_nens) { 				# write file only if sufficient samples (-i)
       
   357 			    
       
   358 				open(P,">$file") || die("$file: $!\n"); 		# open file and output metadata
       
   359 				print(P "#!/usr/bin/perl -S list\n");
       
   360 				print(P "#ANTS# $cmdline\n");
       
   361 				printf(P "#ANTS#PARAMS# " .
       
   362 						"PD0_file{$ARGV[0]} " .
       
   363 						"dn{%s} " .
       
   364 						"N_ensembles{%d} ensemble_range{%d,%d} " .
       
   365 						"delta-T{%g} " .
       
   366 						"soundspeed_correction{%s} " .
       
   367 						"magnetic_declination{%g} " .
       
   368 						"\n",
       
   369 							&dde($dn_s,$dn_n),
       
   370 							$a1_n[0],$feib,$leib,$deltaT,
       
   371 							(defined($opt_S) ? $opt_S : "NONE!"),
       
   372 							$opt_M
       
   373 
       
   374 				);
       
   375 			    
       
   376 				print(P "#ANTS#FIELDS# " .													# Layout
       
   377 						"{bin} {dz} {u} {v} {w} {e} {w12} {w34} {corr1} {corr2} {corr3} {corr4} " .
       
   378 						"{amp1} {amp2} {amp3} {amp4} "
       
   379 				);
       
   380 				if ($beamCoords) {
       
   381 					print(P "{pcg1} {pcg2} {pcg3} {pcg4} ");
       
   382 				} else {
       
   383 					print(P "{pc3beam} {pcBadErrVel} {pc1or2beam} {pc4beam} ");
       
   384 				}
       
   385 				print(P "{uvw.nsamp} {e.nsamp} ");
       
   386 				print(P "$addLayout\n");
       
   387 																							# ssCorr for dz based on first ensemble in bin
       
   388 				my($ssCorr) = defined($opt_S)
       
   389 							? ssCorr($dta{ENSEMBLE}[$feib-$dta{ENSEMBLE}[0]->{NUMBER}],$SS_salin,$SS_temp,$SS_depth)
       
   390 							: 1;
       
   391 				for (my($b)=0; $b<$dta{N_BINS}; $b++) { 									# output data
       
   392 					my($dz) = $ssCorr * ($dta{DISTANCE_TO_BIN1_CENTER} + $b*$dta{BIN_LENGTH});
       
   393 					printf(P "%d %g  %g %g %g %g  %g %g  %d %d %d %d  %d %d %d %d  %d %d %d %d	%d %d",
       
   394 						$b+1,$dz,
       
   395 						&dde($v1[$b],$v1_n[$b]),&dde($v2[$b],$v2_n[$b]),&dde($v3[$b],$v3_n[$b]),&dde($v4[$b],$v4_n[$b]),
       
   396 						&dde($w12[$b],$w12_n[$b]),&dde($w34[$b],$w34_n[$b]),
       
   397 						&dde($c1[$b],$c1_n[$b]),&dde($c2[$b],$c2_n[$b]),&dde($c3[$b],$c3_n[$b]),&dde($c4[$b],$c4_n[$b]),
       
   398 						&dde($a1[$b],$a1_n[$b]),&dde($a2[$b],$a2_n[$b]),&dde($a3[$b],$a3_n[$b]),&dde($a4[$b],$a4_n[$b]),
       
   399 						&dde($p1[$b],$p1_n[$b]),&dde($p2[$b],$p2_n[$b]),&dde($p3[$b],$p3_n[$b]),&dde($p4[$b],$p4_n[$b]),
       
   400 						$v1_n[$b],$v4_n[$b]
       
   401 					);
       
   402 
       
   403 					for (my($i)=0; $i<@af; $i++) {
       
   404 						printf(P "%g ",&dde($af[$i][$b],$af_n[$i][$b]));
       
   405 					}
       
   406 					print(P "\n");
       
   407 				}
       
   408 				chmod(0777&~umask,*P);														# activate output
       
   409 				close(P);
       
   410 			} # if -i check okay
       
   411 
       
   412 			for (my($b)=0; $b<$dta{N_BINS}; $b++) { 										# reset stats	 
       
   413 				$v1[$b] = $v1_n[$b] = $v2[$b] = $v2_n[$b] = $v3[$b] = $v3_n[$b] = $v4[$b] = $v4_n[$b] = 0;
       
   414 				$w12[$b] = $w12_n[$b] = $w34[$b] = $w34_n[$b] = 0;
       
   415 				$c1[$b] = $c1_n[$b] = $c2[$b] = $c2_n[$b] = $c3[$b] = $c3_n[$b] = $c4[$b] = $c4_n[$b] = 0;							    
       
   416 				$a1[$b] = $a1_n[$b] = $a2[$b] = $a2_n[$b] = $a3[$b] = $a3_n[$b] = $a4[$b] = $a4_n[$b] = 0;
       
   417 				$p1[$b] = $p1_n[$b] = $p2[$b] = $p2_n[$b] = $p3[$b] = $p3_n[$b] = $p4[$b] = $p4_n[$b] = 0;
       
   418 				for (my($i)=0; $i<@af; $i++) {
       
   419 					$af[$i][$b] = $af_n[$i][$b] = 0;
       
   420 				}
       
   421 				$dn_s = $dn_n = 0;															# day number
       
   422 			}
       
   423 				    
       
   424 			undef($feib);																	# make sure first ensemble in bin will be updated below
       
   425 		} # if time bin is full
       
   426 
       
   427 		$feib = $dta{ENSEMBLE}[$e]->{NUMBER} unless defined($feib); 						# update first and last ensembles in current bin
       
   428 		$leib = $dta{ENSEMBLE}[$e]->{NUMBER};
       
   429 
       
   430 		$dn_s += $dn; $dn_n++;																# day number
       
   431 		    
       
   432 		my($ssCorr) = defined($opt_S) ? ssCorr($dta{ENSEMBLE}[$e],$SS_salin,$SS_temp,$SS_depth) : 1;
       
   433 		for (my($b)=0; $b<$dta{N_BINS}; $b++) {
       
   434 			my(@v,$this_w12,$this_w34);
       
   435 			if ($beamCoords) {																# convert to earth coordinates
       
   436 				undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][0])
       
   437 					if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][0] < $opt_p) || ($opt_d == 1));
       
   438 				undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][1])
       
   439 					if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][1] < $opt_p) || ($opt_d == 2));
       
   440 				undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][2])
       
   441 					if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][2] < $opt_p) || ($opt_d == 3));
       
   442 				undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][3])
       
   443 					if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][3] < $opt_p) || ($opt_d == 4));
       
   444 				($dummy,$this_w12,$dummy,$this_w34) =
       
   445 					velBeamToBPEarth(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
       
   446 				@v = $opt_b ? @{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]} :
       
   447 							  velBeamToEarth(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
   207 			} else {
   448 			} else {
   208 				print(P "{pc3beam} {pcBadErrVel} {pc1or2beam} {pc4beam}");
   449 				@v = velApplyHdgBias(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
   209 			}
   450 			}
   210 			print(P "$addLayout\n");
   451 			$v[0] *= $ssCorr if defined($v[0]); $v[1] *= $ssCorr if defined($v[1]); 		# apply sound-speed correction
   211 			    
   452 			$v[2] *= $ssCorr if defined($v[2]); $v[3] *= $ssCorr if defined($v[3]);
   212 			for (my($b)=0; $b<$dta{N_BINS}; $b++) {
   453 			$w12  *= $ssCorr if defined($w12);	$w34  *= $ssCorr if defined($w34);
   213 				my(@v,$w12,$w34);
   454     
   214 				my($dz) = $dta{DISTANCE_TO_BIN1_CENTER} + $b*$dta{BIN_LENGTH};
   455 			$v1[$b]+=$v[0],$v1_n[$b]++ if defined($v[0]);									# update sums and nsamps
   215 		
   456 			$v2[$b]+=$v[1],$v2_n[$b]++ if defined($v[1]);
   216 				if ($beamCoords) {
   457 			$v3[$b]+=$v[2],$v3_n[$b]++ if defined($v[2]);
   217 					undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][0])
   458 			$v4[$b]+=$v[3],$v4_n[$b]++ if defined($v[3]);
   218 						if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][0] < $opt_p) || ($opt_d == 1));
   459 			$w12[$b]+=$this_w12,$w12_n[$b]++ if defined($this_w12);
   219 					undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][1])
   460 			$w34[$b]+=$this_w34,$w34_n[$b]++ if defined($this_w34);
   220 						if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][1] < $opt_p) || ($opt_d == 2));
   461 			$c1[$b]+=$dta{ENSEMBLE}[$e]->{CORRELATION}[$b][0],$c1_n[$b]++;
   221 					undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][2])
   462 			$c2[$b]+=$dta{ENSEMBLE}[$e]->{CORRELATION}[$b][1],$c2_n[$b]++;
   222 						if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][2] < $opt_p) || ($opt_d == 3));
   463 			$c3[$b]+=$dta{ENSEMBLE}[$e]->{CORRELATION}[$b][2],$c3_n[$b]++;
   223 					undef($dta{ENSEMBLE}[$e]->{VELOCITY}[$b][3])
   464 			$c4[$b]+=$dta{ENSEMBLE}[$e]->{CORRELATION}[$b][3],$c4_n[$b]++;
   224 						if (($dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][3] < $opt_p) || ($opt_d == 4));
   465 			$a1[$b]+=$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b][0],$a1_n[$b]++;
   225 					($dummy,$w12,$dummy,$w34) =
   466 			$a2[$b]+=$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b][1],$a2_n[$b]++;
   226 						velBeamToBPEarth(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
   467 			$a3[$b]+=$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b][2],$a3_n[$b]++;
   227 					@v = $opt_b ? @{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]} :
   468 			$a4[$b]+=$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b][3],$a4_n[$b]++;
   228 							velInstrumentToEarth(\%dta,$e,
   469 			$p1[$b]+=$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][0],$p1_n[$b]++;
   229 								velBeamToInstrument(\%dta,
   470 			$p2[$b]+=$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][1],$p2_n[$b]++;
   230 									@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]}));
   471 			$p3[$b]+=$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][2],$p3_n[$b]++;
   231 				} else {
   472 			$p4[$b]+=$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b][3],$p4_n[$b]++;
   232 					@v = velApplyHdgBias(\%dta,$e,@{$dta{ENSEMBLE}[$e]->{VELOCITY}[$b]});
   473 
   233 				}
   474 			my($fi) = 0;
   234 		
       
   235 				$v[0] = nan unless defined($v[0]);		# u
       
   236 				$v[1] = nan unless defined($v[1]);		# v
       
   237 				$v[2] = nan unless defined($v[2]);		# w
       
   238 				$v[3] = nan unless defined($v[3]);		# err_vel
       
   239 				$w12 = nan unless defined($w12);		# w from beams 1&2
       
   240 				$w34 = nan unless defined($w34);		# w from beams 3&4
       
   241 
       
   242 				my(@out);
       
   243 				if ($opt_B) {
       
   244 					$v[0] = nan unless defined($dta{ENSEMBLE}[$e]->{BT_VELOCITY}[0]);
       
   245 					$v[1] = nan unless defined($dta{ENSEMBLE}[$e]->{BT_VELOCITY}[1]);
       
   246 					@out = (
       
   247 						$b,$dz,$v[0]-$dta{ENSEMBLE}[$e]->{BT_VELOCITY}[0],
       
   248 						$v[1]-$dta{ENSEMBLE}[$e]->{BT_VELOCITY}[1],$v[2],$v[3],$w12,$w34,
       
   249 						@{$dta{ENSEMBLE}[$e]->{CORRELATION}[$b]},
       
   250 						@{$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b]},
       
   251 						@{$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b]}
       
   252 					);
       
   253 				} else {
       
   254 					@out = (
       
   255 						$b,$dz,$v[0],$v[1],$v[2],$v[3],$w12,$w34,
       
   256 						@{$dta{ENSEMBLE}[$e]->{CORRELATION}[$b]},
       
   257 						@{$dta{ENSEMBLE}[$e]->{ECHO_AMPLITUDE}[$b]},
       
   258 						@{$dta{ENSEMBLE}[$e]->{PERCENT_GOOD}[$b]}
       
   259 					);
       
   260 				}
       
   261 				foreach my $f (@addFields) {
       
   262 					my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)});
       
   263 					$fn = $f unless defined($fn);
       
   264 					push(@out,eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi"));
       
   265 				}
       
   266 				for ($i=0; $i<19+@addFields; $i++) {
       
   267 					$out[$i] = nan unless defined($out[$i]);
       
   268 				}
       
   269 				print(P "@out\n");
       
   270 			}
       
   271 			close(P);
       
   272 		}
       
   273 
       
   274 	} else {											# neither ANTS nor ens files
       
   275 		unless ($opt_Q) {
       
   276 			if ($dta{FIXED_LEADER_BYTES} >= 53) {
       
   277 				printf("    # Date       Time        XD  Temp Headng Pitch  Roll #vv DSID ESW$addLayout\n");
       
   278 				printf("-----------------------------------------------------------------------\n");
       
   279 			} else {
       
   280 				printf("    # Date       Time        XD  Temp Headng Pitch  Roll #vv DSID$addLayout\n");
       
   281 				printf("-------------------------------------------------------------------\n");
       
   282 			}
       
   283 		}
       
   284 
       
   285 		$dumpEns = sub ($)
       
   286 		{
       
   287 			my($e) = @_;
       
   288 
       
   289 			printf('%5d %s %s %s %5.1f',
       
   290 				$dta{ENSEMBLE}[$e]->{NUMBER},
       
   291 				$dta{ENSEMBLE}[$e]->{DATE},
       
   292 				$dta{ENSEMBLE}[$e]->{TIME},
       
   293 				$dta{ENSEMBLE}[$e]->{XDUCER_FACING_UP} ? "UP" : "DN",
       
   294 				$dta{ENSEMBLE}[$e]->{TEMPERATURE},
       
   295 			);
       
   296 			if (defined($dta{ENSEMBLE}[$e]->{HEADING})) { printf(' %6.1f',$dta{ENSEMBLE}[$e]->{HEADING}); }
       
   297 			else { printf('    nan'); }
       
   298 			if (defined($dta{ENSEMBLE}[$e]->{PITCH})) { printf(' %5.1f',$dta{ENSEMBLE}[$e]->{PITCH}); }
       
   299 			else { printf('   nan'); }
       
   300 			if (defined($dta{ENSEMBLE}[$e]->{ROLL})) { printf(' %5.1f',$dta{ENSEMBLE}[$e]->{ROLL}); }
       
   301 			else { printf('   nan'); }
       
   302 			printf(' %3d 0x%02X',
       
   303 				$dta{ENSEMBLE}[$e]->{BIN1VELS},
       
   304 				$dta{ENSEMBLE}[$e]->{DATA_SOURCE_ID},
       
   305 			);
       
   306 			printf(' 0x%08X',$dta{ENSEMBLE}[$e]->{ERROR_STATUS_WORD})
       
   307 				if ($dta{FIXED_LEADER_BYTES} >= 53);
       
   308 			foreach my $f (@addFields) {
   475 			foreach my $f (@addFields) {
   309 				my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)});
   476 				my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)});
   310 				$fn = $f unless defined($fn);
   477 				$fn = $f unless defined($fn);
   311 				my($v) = eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi");
   478 				my($val) = eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi");
   312 				print(defined($v) ? " $v" : " nan");
   479 				$af[$fi][$b]+=$val,$af_n[$fi][$b]++ if defined($val);
       
   480 				$fi++;
   313 			}
   481 			}
   314 			print(" BUILT-IN-TEST ERROR")
       
   315 				if defined($dta{ENSEMBLE}[$e]->{BUILT_IN_TEST_ERROR});
       
   316 			print("\n");
       
   317 		}
   482 		}
   318 		
   483 	}
   319 	}
   484 
   320 
   485 } else {											# neither ANTS nor ens files (DEFAULT OUTPUT)
   321 	for ($e=0; $e<=$#{$dta{ENSEMBLE}}; $e++) {
   486 	if ($dta{FIXED_LEADER_BYTES} >= 53) {
   322 		next if (defined($first_ens) &&
   487 		printf("Ens # Date		 Time		 XD  Temp Headng Pitch	Roll #vv DSID ESW$addLayout\n");
   323 				 $dta{ENSEMBLE}[$e]->{NUMBER} < $first_ens);
   488 		printf("----------------------------------------------------------------------------\n");
   324 		last if (defined($last_ens) &&
   489 	} else {
   325 				 $dta{ENSEMBLE}[$e]->{NUMBER} > $last_ens);
   490 		printf("Ens # Date		 Time		 XD  Temp Headng Pitch	Roll #vv DSID$addLayout\n");
   326 		 $dta{ENSEMBLE}[$e]->{BIN1VELS} =
   491 		printf("------------------------------------------------------------------------\n");
   327 				defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][0]) +
   492 	}
   328 				defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][1]) +
   493 
   329 				defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][2]) +
   494 	$dumpEns = sub ($)
   330 	            defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][3]);
   495 	{
   331 		next if ($opt_w && $dta{ENSEMBLE}[$e]->{BIN1VELS}<3);
   496 		my($e) = @_;
   332 
   497 
   333 		die("3-beams used in ensemble #$dta{ENSEMBLE}[$e]->{NUMBER}\n")
   498 		printf('%5d %s %s %s %5.1f',
   334 			if ($dta{ENSEMBLE}[$e]->{N_BEAMS_USED} < 4);
   499 			$dta{ENSEMBLE}[$e]->{NUMBER},
   335 		die("BIT error in ensemble $dta{ENSEMBLE}[$e]->{NUMBER}\n")
   500 			$dta{ENSEMBLE}[$e]->{DATE},
   336 			if ($opt_Q || $opt_A || $opt_E) && defined($dta{ENSEMBLE}[$e]->{BUILT_IN_TEST_ERROR});
   501 			$dta{ENSEMBLE}[$e]->{TIME},
   337 		die("Low gain in ensemble #$dta{ENSEMBLE}[$e]->{NUMBER}\n")
   502 			$dta{ENSEMBLE}[$e]->{XDUCER_FACING_UP} ? "UP" : "DN",
   338 			if ($dta{ENSEMBLE}[$e]->{LOW_GAIN});
   503 			$dta{ENSEMBLE}[$e]->{TEMPERATURE},
   339 
   504 		);
   340 		&$dumpEns($e)
   505 		if (defined($dta{ENSEMBLE}[$e]->{HEADING})) { printf(' %6.1f',$dta{ENSEMBLE}[$e]->{HEADING}); }
   341 			unless ($opt_Q);
   506 		else { printf('    nan'); }
   342 	}
   507 		if (defined($dta{ENSEMBLE}[$e]->{PITCH})) { printf(' %5.1f',$dta{ENSEMBLE}[$e]->{PITCH}); }
       
   508 		else { printf('   nan'); }
       
   509 		if (defined($dta{ENSEMBLE}[$e]->{ROLL})) { printf(' %5.1f',$dta{ENSEMBLE}[$e]->{ROLL}); }
       
   510 		else { printf('   nan'); }
       
   511 		printf(' %3d 0x%02X',
       
   512 			$dta{ENSEMBLE}[$e]->{BIN1VELS},
       
   513 			$dta{ENSEMBLE}[$e]->{DATA_SOURCE_ID},
       
   514 		);
       
   515 		printf(' 0x%08X',$dta{ENSEMBLE}[$e]->{ERROR_STATUS_WORD})
       
   516 			if ($dta{FIXED_LEADER_BYTES} >= 53);
       
   517 		foreach my $f (@addFields) {
       
   518 			my($fn,$fi) = ($f =~ m{([^[]*)(\[.*)});
       
   519 			$fn = $f unless defined($fn);
       
   520 			my($v) = eval("\$dta{ENSEMBLE}[$e]->{$fn}$fi");
       
   521 			print(defined($v) ? " $v" : " nan");
       
   522 		}
       
   523 		print(" BUILT-IN-TEST ERROR")
       
   524 			if defined($dta{ENSEMBLE}[$e]->{BUILT_IN_TEST_ERROR});
       
   525 		print("\n");
       
   526 	}
       
   527 } # define output format
       
   528 
       
   529 #----------------------------------------------------------------------
       
   530 # Loop Over Ensembles
       
   531 #----------------------------------------------------------------------
       
   532 
       
   533 for ($e=0; $e<=$#{$dta{ENSEMBLE}}; $e++) {
       
   534 	 $dta{ENSEMBLE}[$e]->{BIN1VELS} =
       
   535 			defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][0]) +
       
   536 			defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][1]) +
       
   537 			defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][2]) +
       
   538 			defined($dta{ENSEMBLE}[$e]->{VELOCITY}[1][3]);
       
   539 	next if ($opt_w && $dta{ENSEMBLE}[$e]->{BIN1VELS}<3);
       
   540 
       
   541 	die("BIT error in ensemble $dta{ENSEMBLE}[$e]->{NUMBER}\n")
       
   542 		if ($opt_A || $dump_ens) && defined($dta{ENSEMBLE}[$e]->{BUILT_IN_TEST_ERROR});
       
   543 	die("Low gain in ensemble #$dta{ENSEMBLE}[$e]->{NUMBER}\n")
       
   544 		if ($dta{ENSEMBLE}[$e]->{LOW_GAIN});
       
   545 
       
   546 	&$dumpEns($e);
   343 }
   547 }
   344 
   548 
       
   549 &$dumpEns(-1) if defined($opt_T);										# dump final bin
       
   550 
   345 exit(0);	
   551 exit(0);