.
authorA.M. Thurnherr <athurnherr@yahoo.com>
Thu, 29 May 2014 08:41:19 +0000
changeset 18 bb7bb9f83db9
parent 17 591779f6df30
child 19 e23a5fd2923a
.
RDI_Coords.pl
RDI_PD0_IO.pl
beamStats
listBins
listEns
listHdr
mkProfile
splitRDI
--- a/RDI_Coords.pl
+++ b/RDI_Coords.pl
@@ -1,9 +1,9 @@
 #======================================================================
 #                    R D I _ C O O R D S . P L 
 #                    doc: Sun Jan 19 17:57:53 2003
-#                    dlm: Sat Feb 22 09:43:27 2014
+#                    dlm: Tue Mar  4 13:35:21 2014
 #                    (c) 2003 A.M. Thurnherr
-#                    uE-Info: 37 0 NIL 0 0 72 0 2 4 NIL ofnI
+#                    uE-Info: 273 60 NIL 0 0 72 0 2 4 NIL ofnI
 #======================================================================
 
 # RDI Workhorse Coordinate Transformations
@@ -34,6 +34,7 @@
 #	Aug  7, 2013: - BUG: &velBeamToBPInstrument did not return any val unless
 #						 all beam velocities are defined
 #	Nov 27, 2013: - added &RDI_pitch(), &tilt_azimuth()
+#	Mar  4, 2014: - added support for missing PITCH/ROLL/HEADING
 
 use strict;
 use POSIX;
@@ -111,7 +112,10 @@
 	{
 		my($dta,$ens,$v1,$v2,$v3,$v4) = @_;
 		return undef unless (defined($v1) && defined($v2) &&
-					   		 defined($v3) && defined($v4));
+					   		 defined($v3) && defined($v4) &&
+							 defined($dta->{ENSEMBLE}[$ens]->{PITCH}) &&
+							 defined($dta->{ENSEMBLE}[$ens]->{ROLL}) &&
+							 defined($dta->{ENSEMBLE}[$ens]->{HEADING}));
 	
 		unless (@I2E &&
 				$hdg   == $dta->{ENSEMBLE}[$ens]->{HEADING}
@@ -162,6 +166,11 @@
 		my($dta,$ens,$b1,$b2,$b3,$b4) = @_;
 		my($v12,$w12,$v34,$w34);
 
+		return (undef,undef,undef,undef) 
+			unless (defined($dta->{ENSEMBLE}[$ens]->{PITCH}) &&
+                    defined($dta->{ENSEMBLE}[$ens]->{ROLL}) &&
+                    defined($dta->{ENSEMBLE}[$ens]->{HEADING}));
+
 		unless (defined($TwoCosBAngle)) {
 			$TwoCosBAngle = 2 * cos(rad($dta->{BEAM_ANGLE}));
 			$TwoSinBAngle = 2 * sin(rad($dta->{BEAM_ANGLE}));
@@ -216,6 +225,11 @@
 		my($dta,$ens,$b1,$b2,$b3,$b4) = @_;
 		my($v12,$w12,$v34,$w34);
 
+		return (undef,undef,undef,undef) 
+			unless (defined($dta->{ENSEMBLE}[$ens]->{PITCH}) &&
+                    defined($dta->{ENSEMBLE}[$ens]->{ROLL}) &&
+                    defined($dta->{ENSEMBLE}[$ens]->{HEADING}));
+
 		unless (defined($TwoCosBAngle)) {
 			$TwoCosBAngle = 2 * cos(rad($dta->{BEAM_ANGLE}));
 			$TwoSinBAngle = 2 * sin(rad($dta->{BEAM_ANGLE}));
@@ -254,7 +268,9 @@
 sub velApplyHdgBias(@)
 {
 	my($dta,$ens,$v1,$v2,$v3,$v4) = @_;
-	return undef unless (defined($v1) && defined($v2));
+	return (undef,undef,undef,undef) 
+		unless (defined($v1) && defined($v2) &&
+				defined($dta->{ENSEMBLE}[$ens]->{HEADING}));
 
 	my($sh) = sin(rad(-$dta->{HEADING_BIAS}));
 	my($ch) = cos(rad(-$dta->{HEADING_BIAS}));
@@ -272,22 +288,25 @@
 sub gimbal_pitch($$)	# RDI coord trans manual
 {
 	my($RDI_pitch,$RDI_roll) = @_;
+	return 'nan' unless defined($RDI_pitch) && defined($RDI_roll);
 	return deg(atan(tan(rad($RDI_pitch)) * cos(rad($RDI_roll))));
 }
 
 sub RDI_pitch($$)
 {
 	my($gimbal_pitch,$roll) = @_;
+	return 'nan' unless defined($gimbal_pitch) && defined($roll);
 	return deg(atan(tan(rad($gimbal_pitch))/cos(rad($roll))));
 }
 
 sub tilt_azimuth($$)
 {
 	my($gimbal_pitch,$roll) = @_;
+	return 'nan' unless defined($gimbal_pitch) && defined($roll);
 	return angle(deg(atan2(sin(rad($gimbal_pitch)),sin(rad($roll)))));
 }
 
-# - angle from vertical is home grown and should be treated with caution
+# - angle from vertical is home grown
 # - angle between two unit vectors given by acos(v1 dot v2)
 # - vertical unit vector v1 = (0 0 1) => dot product = z-component of v2
 # - when vertical unit vector is pitched in x direction, followed by
@@ -301,6 +320,7 @@
 sub angle_from_vertical($$)
 {
 	my($RDI_pitch,$RDI_roll) = @_;
+	return 'nan' unless defined($RDI_pitch) && defined($RDI_roll);
 	my($rad_pitch) = atan(tan(rad($RDI_pitch)) * cos(rad($RDI_roll)));
 	return deg(acos(cos($rad_pitch) * cos(rad($RDI_roll))));
 }
--- a/RDI_PD0_IO.pl
+++ b/RDI_PD0_IO.pl
@@ -1,9 +1,9 @@
 #======================================================================
 #                    R D I _ P D 0 _ I O . P L 
 #                    doc: Sat Jan 18 14:54:43 2003
-#                    dlm: Tue Nov 26 01:29:26 2013
+#                    dlm: Wed May  7 10:41:18 2014
 #                    (c) 2003 A.M. Thurnherr
-#                    uE-Info: 873 10 NIL 0 0 72 74 2 4 NIL ofnI
+#                    uE-Info: 827 0 NIL 0 0 72 74 2 4 NIL ofnI
 #======================================================================
 
 # Read RDI BroadBand Binary Data Files (*.[0-9][0-9][0-9])
@@ -54,6 +54,11 @@
 #	Nov 25, 2013: - renamed from [RDI_BB_Read.pl]
 #				  - begin implementing WBWens()
 #				  - checkEnsemble() expunged
+#	Mar  3, 2014: - BUG: WBPens() did not handle incomple ensembles at EOF correctly
+#	Mar  4, 2014: - added support for DATA_SOURCE_ID
+#	Apr 24, 2014: - added debug statements to log %-GOOD values
+#	May  6, 2014: - loosened input format checks
+#	May  7, 2014: - removed BT_present flag
 
 # FIRMWARE VERSIONS:
 #	It appears that different firmware versions generate different file
@@ -67,6 +72,14 @@
 #	16.21	WH300 (1)				LDEO 	NBP0402		53
 #	16.27	WH300 (2)				Nash 	?			59
 
+# PD0 IMP FILE FORMAT EXTENSIONS:
+#	- DATA_SOURCE_ID = 0xA0 | PATCHED_MASK (vs. 0x7F for TRDI PD0 files)
+#		PATCHED_MASK & 0x04:	pitch value has been patched
+#		PATCHED_MASK & 0x02:	roll value has been patched
+#		PATCHED_MASK & 0x01:	heading value has been patched
+#	- PITCH & ROLL can be missing (0x8000 badval as in velocities)
+#	- HEADING can be missing (0xF000 badval, as 0x8000 is valid 327.68 heading)
+
 # NOTES:
 #	- RDI stores data in VAX/Intel byte order (little endian)
 #	- the output data structure does not exactly mirror the file data
@@ -99,6 +112,7 @@
 # &readData() returns perl obj (ref to anonymous hash) with the following
 # structure:
 #
+#	DATA_SOURCE_ID					scalar		0x7f (Workhorse, also DVL)
 #	NUMBER_OF_DATA_TYPES			scalar		6 (no BT) or 7
 #	ENSEMBLE_BYTES					scalar		?, number of bytes w/o checksum
 #	HEADER_BYTES					scalar		?
@@ -183,9 +197,9 @@
 #		BUILT_IN_TEST_ERROR			scalar		?,undefined=none
 #		SPEED_OF_SOUND				scalar		1400--1600 [m/s]
 #		XDUCER_DEPTH				scalar		0.1--999.9 [m]
-#		HEADING						scalar		0--359.99 [deg]
-#		PITCH						scalar		-20.00-20.00 [deg]
-#		ROLL						scalar		-20.00-20.00 [deg]
+#		HEADING						scalar		0--359.99 [deg]    --- IMP EXTENSION: undef
+#		PITCH						scalar		-20.00-20.00 [deg] --- IMP EXTENSION: undef
+#		ROLL						scalar		-20.00-20.00 [deg] --- IMP EXTENSION: undef
 #		SALINITY					scalar		0-40 [psu]
 #		TEMPERATURE					scalar		-5.00--40.00 [deg]
 #		MIN_PRE_PING_WAIT_TIME		scalar		? [s]
@@ -317,7 +331,7 @@
 	($hid,$did,$dta->{ENSEMBLE_BYTES},$dummy,$dta->{NUMBER_OF_DATA_TYPES})
 		= unpack('CCvCC',$buf);
 	$hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header",$hid,0));
-	$did == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Data Source",$did,0));
+##	$did == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Data Source",$did,0));
 	printf(STDERR "\n$WBRcfn: WARNING: unexpected number of data types (%d)\n",
 		$dta->{NUMBER_OF_DATA_TYPES})
 			unless ($dta->{NUMBER_OF_DATA_TYPES} == 6 ||
@@ -553,7 +567,7 @@
 {
 	my($nbins,$fixed_leader_bytes,$E) = @_;
 	my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBRofs);
-	my($ens,$ensNo,$dayStart,$ens_length,$BT_present,$hid,$did,$ndt);
+	my($ens,$ensNo,$dayStart,$ens_length,$hid,$did,$ndt);
 
 	for ($ens=$start_ens=0; 1; $ens++,$start_ens+=$ens_length+2) {
 #		print(STDERR "ens = $ens\n");
@@ -567,10 +581,9 @@
 		sysread(WBRF,$buf,6) == 6 || last;
 		($hid,$did,$ens_length,$dummy,$ndt) = unpack('CCvCC',$buf);
 		$hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header",$hid,0));
-		$did == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Data Source",$did,0));
-		printf(STDERR "\n$WBRcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last
-				unless ($ndt == 6 || $ndt == 7);
-		$BT_present = ($ndt == 7);
+##		$did == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Data Source",$did,0));
+##		printf(STDERR "\n$WBRcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last
+##				unless ($ndt == 6 || $ndt == 7);
 		sysread(WBRF,$buf,2*$ndt) == 2*$ndt || die("$WBRcfn: $!");
 		@WBRofs = unpack("v$ndt",$buf);
 		$fixed_leader_bytes = $WBRofs[1] - $WBRofs[0];
@@ -594,6 +607,8 @@
 		# Variable Leader
 		#------------------------------
 	
+		${$E}[$ens]->{DATA_SOURCE_ID} = $did;								# IMP extension
+
 		sysseek(WBRF,$start_ens+$WBRofs[1],0) || die("$WBRcfn: $!");
 		sysread(WBRF,$buf,4) == 4 || die("$WBRcfn: $!");
 		($id,$ensNo) = unpack("vv",$buf);
@@ -635,11 +650,22 @@
 		$BIT_errors++ if (${$E}[$ens]->{BUILT_IN_TEST_ERROR});
 
 		${$E}[$ens]->{XDUCER_DEPTH} /= 10;
-		${$E}[$ens]->{HEADING} /= 100;
-		${$E}[$ens]->{PITCH} = unpack('s',pack('S',${$E}[$ens]->{PITCH})) / 100;
-		${$E}[$ens]->{ROLL}  = unpack('s',pack('S',${$E}[$ens]->{ROLL})) / 100;
-		${$E}[$ens]->{TEMPERATURE} =
-			unpack('s',pack('S',${$E}[$ens]->{TEMPERATURE})) / 100;
+
+		#-------------------------------------------------
+		# IMP EXTENSION: PITCH/ROLL/HEADING CAN BE MISSING
+		#-------------------------------------------------
+		
+		${$E}[$ens]->{HEADING} = (${$E}[$ens]->{HEADING} == 0xF000)
+							   ? undef
+							   : ${$E}[$ens]->{HEADING} / 100;
+		${$E}[$ens]->{PITCH} = (${$E}[$ens]->{PITCH} == 0x8000)
+							 ? undef
+							 : unpack('s',pack('S',${$E}[$ens]->{PITCH})) / 100;
+		${$E}[$ens]->{ROLL}  = (${$E}[$ens]->{ROLL} == 0x8000)
+                             ? undef
+                             : unpack('s',pack('S',${$E}[$ens]->{ROLL})) / 100;
+                             
+		${$E}[$ens]->{TEMPERATURE} = unpack('s',pack('S',${$E}[$ens]->{TEMPERATURE})) / 100;
 		${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} *= 60;
 		${$E}[$ens]->{MIN_PRE_PING_WAIT_TIME} += $B1 + $B2/100;
 		${$E}[$ens]->{PITCH_STDDEV} /= 10;
@@ -780,84 +806,90 @@
 			die(sprintf($FmtErr,$WBRcfn,"Percent-Good Data",$id,$ens));
 
 		for ($i=0,$bin=0; $bin<$nbins; $bin++) {
+#			printf(STDERR "%-GOOD($bin): ");
 			for ($beam=0; $beam<4; $beam++,$i++) {
+#				printf(STDERR "$dta[$i] ");
 				${$E}[$ens]->{PERCENT_GOOD}[$bin][$beam] = $dta[$i];
 			}
+#			printf(STDERR "\n");
 		}
 
-		#--------------------
+		#-----------------------------------------
 		# Bottom-Track Data
-		#--------------------
+		#	- scan through remaining data types
+		#-----------------------------------------
 
-		if ($BT_present) {
-			sysseek(WBRF,$start_ens+$WBRofs[6],0) || die("$WBRcfn: $!");
+		my($nxt);
+		for ($nxt=6; $nxt<$ndt; $nxt++) {										# scan until BT found
+			sysseek(WBRF,$start_ens+$WBRofs[$nxt],0) || die("$WBRcfn: $!");
 			sysread(WBRF,$buf,2) == 2 || die("$WBRcfn: $!");
 			$id = unpack('v',$buf);
-	
-			$id == 0x0600 ||
-				die(sprintf($FmtErr,$WBRcfn,"Bottom Track",$id,$ens));
-	
-			sysseek(WBRF,14,1) || die("$WBRcfn: $!");		# BT config
-	
-			sysread(WBRF,$buf,28) == 28 || die("$WBRcfn: $!");
-			@dta = unpack('v4v4C4C4C4',$buf);
-		    
-			for ($beam=0; $beam<4; $beam++) {
-				${$E}[$ens]->{BT_RANGE}[$beam] = $dta[$beam] / 100
-						if ($dta[$beam]);
-			}
-			for ($beam=0; $beam<4; $beam++) {
-				${$E}[$ens]->{BT_VELOCITY}[$beam] =
-					unpack('s',pack('S',$dta[4+$beam])) / 1000
-						if ($dta[4+$beam] != 0x8000);
-			}
-			for ($beam=0; $beam<4; $beam++) {
-				${$E}[$ens]->{BT_CORRELATION}[$beam] = $dta[8+$beam]
-					if ($dta[8+$beam]);
-			}
-			for ($beam=0; $beam<4; $beam++) {
-				${$E}[$ens]->{BT_EVAL_AMPLITUDE}[$beam] = $dta[12+$beam];
-			}
-			for ($beam=0; $beam<4; $beam++) {
-				${$E}[$ens]->{BT_PERCENT_GOOD}[$beam] = $dta[16+$beam];
-			}
-	
-			sysseek(WBRF,6,1) || die("$WBRcfn: $!");		# BT config
-	
-			sysread(WBRF,$buf,20) == 20 || die("$WBRcfn: $!");
-			@dta = unpack('v4C4C4C4',$buf);
-	
-			for ($beam=0; $beam<4; $beam++) {
-				${$E}[$ens]->{BT_RL_VELOCITY}[$beam] =
-					unpack('s',pack('S',$dta[$beam])) / 1000
-						if ($dta[$beam] != 0x8000);
-			}
-			for ($beam=0; $beam<4; $beam++) {
-				${$E}[$ens]->{BT_RL_CORRELATION}[$beam] = $dta[4+$beam]
-					if ($dta[4+$beam]);
-			}
-			for ($beam=0; $beam<4; $beam++) {
-				${$E}[$ens]->{BT_RL_ECHO_AMPLITUDE}[$beam] = $dta[8+$beam];
-			}
-			for ($beam=0; $beam<4; $beam++) {
-				${$E}[$ens]->{BT_RL_PERCENT_GOOD}[$beam] = $dta[12+$beam];
-			}
-	
-			sysseek(WBRF,2,1) || die("$WBRcfn: $!");		# BT config
-	
-			sysread(WBRF,$buf,9) == 9 || die("$WBRcfn: $!");
-			@dta = unpack('C4CC4',$buf);
-	
-			for ($beam=0; $beam<4; $beam++) {
-				${$E}[$ens]->{BT_SIGNAL_STRENGTH}[$beam] = $dta[$beam];
-			}
-			${$E}[$ens]->{HIGH_GAIN} if	   ($dta[4]);
-			${$E}[$ens]->{LOW_GAIN}	unless ($dta[4]);
-			for ($beam=0; $beam<4; $beam++) {
-				${$E}[$ens]->{BT_RANGE}[$beam] += $dta[5+$beam] * 655.36
-					if ($dta[5+$beam]);
-	        }
-	    } # BT present
+			last if ($id == 0x0600);
+		}
+
+		next if ($nxt == $ndt);													# no BT found => next ens
+
+
+		sysseek(WBRF,14,1) || die("$WBRcfn: $!");								# BT config
+
+		sysread(WBRF,$buf,28) == 28 || die("$WBRcfn: $!");
+		@dta = unpack('v4v4C4C4C4',$buf);
+	    
+		for ($beam=0; $beam<4; $beam++) {
+			${$E}[$ens]->{BT_RANGE}[$beam] = $dta[$beam] / 100
+					if ($dta[$beam]);
+		}
+		for ($beam=0; $beam<4; $beam++) {
+			${$E}[$ens]->{BT_VELOCITY}[$beam] =
+				unpack('s',pack('S',$dta[4+$beam])) / 1000
+					if ($dta[4+$beam] != 0x8000);
+		}
+		for ($beam=0; $beam<4; $beam++) {
+			${$E}[$ens]->{BT_CORRELATION}[$beam] = $dta[8+$beam]
+				if ($dta[8+$beam]);
+		}
+		for ($beam=0; $beam<4; $beam++) {
+			${$E}[$ens]->{BT_EVAL_AMPLITUDE}[$beam] = $dta[12+$beam];
+		}
+		for ($beam=0; $beam<4; $beam++) {
+			${$E}[$ens]->{BT_PERCENT_GOOD}[$beam] = $dta[16+$beam];
+		}
+
+		sysseek(WBRF,6,1) || die("$WBRcfn: $!");		# BT config
+
+		sysread(WBRF,$buf,20) == 20 || die("$WBRcfn: $!");
+		@dta = unpack('v4C4C4C4',$buf);
+
+		for ($beam=0; $beam<4; $beam++) {
+			${$E}[$ens]->{BT_RL_VELOCITY}[$beam] =
+				unpack('s',pack('S',$dta[$beam])) / 1000
+					if ($dta[$beam] != 0x8000);
+		}
+		for ($beam=0; $beam<4; $beam++) {
+			${$E}[$ens]->{BT_RL_CORRELATION}[$beam] = $dta[4+$beam]
+				if ($dta[4+$beam]);
+		}
+		for ($beam=0; $beam<4; $beam++) {
+			${$E}[$ens]->{BT_RL_ECHO_AMPLITUDE}[$beam] = $dta[8+$beam];
+		}
+		for ($beam=0; $beam<4; $beam++) {
+			${$E}[$ens]->{BT_RL_PERCENT_GOOD}[$beam] = $dta[12+$beam];
+		}
+
+		sysseek(WBRF,2,1) || die("$WBRcfn: $!");		# BT config
+
+		sysread(WBRF,$buf,9) == 9 || die("$WBRcfn: $!");
+		@dta = unpack('C4CC4',$buf);
+
+		for ($beam=0; $beam<4; $beam++) {
+			${$E}[$ens]->{BT_SIGNAL_STRENGTH}[$beam] = $dta[$beam];
+		}
+		${$E}[$ens]->{HIGH_GAIN} if    ($dta[4]);
+		${$E}[$ens]->{LOW_GAIN} unless ($dta[4]);
+		for ($beam=0; $beam<4; $beam++) {
+			${$E}[$ens]->{BT_RANGE}[$beam] += $dta[5+$beam] * 655.36
+				if ($dta[5+$beam]);
+		}
 	} # ens loop
 }
 
@@ -886,22 +918,28 @@
 {
 	my($nbins,$fixed_leader_bytes,$E) = @_;
 	my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBPofs);
-	my($ens,$ensNo,$dayStart,$ens_length,$BT_present,$hid,$did,$ndt);
+	my($ens,$ensNo,$dayStart,$ens_length,$hid,$ndt);
 
-	for ($ens=$start_ens=0; 1; $ens++,$start_ens+=$ens_length+2) {
+	for ($ens=$start_ens=0; $ens<=$#{$E}; $ens++,$start_ens+=$ens_length+2) {
 
-		#----------------------------------------
-		# Get ensemble length and # of data types 
-		#----------------------------------------
+		#------------------------------
+		# Patch Header (Data Source Id)
+		#------------------------------
 
 		sysseek(WBPF,$start_ens,0) || die("$WBPcfn: $!");
-		sysread(WBPF,$buf,6) == 6 || last;
-		($hid,$did,$ens_length,$dummy,$ndt) = unpack('CCvCC',$buf);
-		$hid == 0x7f || die(sprintf($FmtErr,$WBPcfn,"Header",$hid,0));
-		$did == 0x7f || die(sprintf($FmtErr,$WBPcfn,"Data Source",$did,0));
+		sysread(WBPF,$buf,1) || die("$WBPcfn: unexpected EOF");
+		($hid) = unpack('C',$buf);
+		$hid == 0x7f || die(sprintf($FmtErr,$WBPcfn,"Header",$hid,$ens));
+
+		$buf = pack('C',${$E}[$ens]->{DATA_SOURCE_ID});
+		my($nw) = syswrite(WBPF,$buf,1);
+		$nw == 1 || die("$WBPcfn: $nw bytes written ($!)");
+
+		sysread(WBPF,$buf,4) == 4 || die("$WBPcfn: unexpected EOF");
+		($ens_length,$dummy,$ndt) = unpack('vCC',$buf);
 		printf(STDERR "\n$WBPcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last
 				unless ($ndt == 6 || $ndt == 7);
-		$BT_present = ($ndt == 7);
+
 		sysread(WBPF,$buf,2*$ndt) == 2*$ndt || die("$WBPcfn: $!");
 		@WBPofs = unpack("v$ndt",$buf);
 		$fixed_leader_bytes = $WBPofs[1] - $WBPofs[0];
@@ -913,10 +951,19 @@
 		sysseek(WBPF,$start_ens+$WBPofs[1]+12,0) || die("$WBPcfn: $!");
 		
 		${$E}[$ens]->{XDUCER_DEPTH} *= 10;
-		${$E}[$ens]->{HEADING} *= 100;
-		
-		${$E}[$ens]->{PITCH} = unpack('S',pack('s',${$E}[$ens]->{PITCH}*100));
-		${$E}[$ens]->{ROLL}  = unpack('S',pack('s',${$E}[$ens]->{ROLL} *100));
+
+		# IMP EXTENSIONS
+		#---------------
+		${$E}[$ens]->{HEADING} = defined(${$E}[$ens]->{HEADING})
+							   ? ${$E}[$ens]->{HEADING} * 100
+							   : 0xF000;
+		${$E}[$ens]->{PITCH} = defined(${$E}[$ens]->{PITCH})
+							 ? unpack('S',pack('s',${$E}[$ens]->{PITCH}*100))
+							 : 0x8000;
+		${$E}[$ens]->{ROLL} = defined(${$E}[$ens]->{ROLL})
+						    ? unpack('S',pack('s',${$E}[$ens]->{ROLL}*100))
+						    : 0x8000;
+
 		${$E}[$ens]->{TEMPERATURE} =
 			unpack('S',pack('s',${$E}[$ens]->{TEMPERATURE}*100));
 
@@ -933,20 +980,6 @@
 			 ${$E}[$ens]->{PITCH},${$E}[$ens]->{ROLL},
 			 ${$E}[$ens]->{SALINITY},${$E}[$ens]->{TEMPERATURE});
 
-#		unless ($b1 eq $buf) {
-#			printf(STDERR "ens = $ens\n");
-#			printf(STDERR "hdg: $hdg, ${$E}[$ens]->{HEADING}\n");
-#			printf(STDERR "xd: $xd, ${$E}[$ens]->{XDUCER_DEPTH}\n");
-#			printf(STDERR "pit: $pit, ${$E}[$ens]->{PITCH}\n");
-#			printf(STDERR "rol: $rol, ${$E}[$ens]->{ROLL}\n");
-#			printf(STDERR "sal: $sal, ${$E}[$ens]->{SALINITY}\n");
-#			printf(STDERR "tem: $tem, ${$E}[$ens]->{TEMPERATURE}\n");
-#
-#			printf(STDERR "read: %04X %04X %04X %04X %04X %04X %04X written: %04X %04X %04X %04X %04X %04X %04X\n",unpack('v7',$b1),unpack('v7',$buf));
-#
-#			die;
-#		}
-
 		my($nw) = syswrite(WBPF,$buf,14);
 		$nw == 14 || die("$WBPcfn: $nw bytes written ($!)");
 
--- a/beamStats
+++ b/beamStats
@@ -1,10 +1,10 @@
 #!/usr/bin/perl
 #======================================================================
-#                    L I S T B I N S 
+#                    B E A M S T A T S 
 #                    doc: Fri Aug 25 15:57:05 2006
-#                    dlm: Thu Feb 21 15:05:40 2008
+#                    dlm: Tue Mar  4 13:09:14 2014
 #                    (c) 2006 A.M. Thurnherr
-#                    uE-Info: 32 57 NIL 0 0 72 0 2 4 NIL ofnI
+#                    uE-Info: 33 64 NIL 0 0 72 0 2 4 NIL ofnI
 #======================================================================
 
 # Split data file into per-bin time series.
@@ -30,6 +30,7 @@
 #					BUG: min() did not work with 1st elt undef
 #	Feb 21, 2008: - BUG: had forgotten to undo debugging changes
 #				  - removed missing magdecl warning on -b
+#	Mar  4, 2014: - added support for missing PITCH/ROLL/HEADING
 
 # General Notes:
 #	- everything (e.g. beams) is numbered from 1
@@ -160,9 +161,9 @@
 		print(P "$dta{ENSEMBLE}[$e]->{DATE} ");
 		print(P "$dta{ENSEMBLE}[$e]->{TIME} ");
 		printf(P "%d ",$dta{ENSEMBLE}[$e]->{UNIX_TIME}-$t0);
-		print(P "$dta{ENSEMBLE}[$e]->{HEADING} ");
-		print(P "$dta{ENSEMBLE}[$e]->{PITCH} ");
-		print(P "$dta{ENSEMBLE}[$e]->{ROLL} ");
+		print(P defined($dta{ENSEMBLE}[$e]->{HEADING}) ? "$dta{ENSEMBLE}[$e]->{HEADING} " : 'nan ');
+		print(P defined($dta{ENSEMBLE}[$e]->{PITCH}) ? "$dta{ENSEMBLE}[$e]->{PITCH} " : 'nan ');
+		print(P defined($dta{ENSEMBLE}[$e]->{ROLL}) ? "$dta{ENSEMBLE}[$e]->{ROLL} " : 'nan ');
 		print(P "$dta{ENSEMBLE}[$e]->{HEADING_STDDEV} ");
 		print(P "$dta{ENSEMBLE}[$e]->{PITCH_STDDEV} ");
 		print(P "$dta{ENSEMBLE}[$e]->{ROLL_STDDEV} ");
--- a/listBins
+++ b/listBins
@@ -2,9 +2,9 @@
 #======================================================================
 #                    L I S T B I N S 
 #                    doc: Fri Aug 25 15:57:05 2006
-#                    dlm: Wed Aug  7 10:04:28 2013
+#                    dlm: Tue Apr 22 12:39:09 2014
 #                    (c) 2006 A.M. Thurnherr
-#                    uE-Info: 48 46 NIL 0 0 72 2 2 4 NIL ofnI
+#                    uE-Info: 50 45 NIL 0 0 72 2 2 4 NIL ofnI
 #======================================================================
 
 # Split data file into per-bin time series.
@@ -46,6 +46,8 @@
 #	Apr 29, 2013: - cosmetics
 #				  - added warning on missing -S
 #	Aug  7, 2013: - BUG: -w did not respect -d
+#   Mar  4, 2014: - added support for missing PITCH/ROLL/HEADING
+#	Apr 22, 2014: - BUG: extraneous semicolon
 
 # General Notes:
 #	- everything (e.g. beams) is numbered from 1
@@ -174,9 +176,9 @@
 		print(P "$dta{ENSEMBLE}[$e]->{DATE} ");
 		print(P "$dta{ENSEMBLE}[$e]->{TIME} ");
 		printf(P "%d ",$dta{ENSEMBLE}[$e]->{UNIX_TIME}-$t0);
-		print(P "$dta{ENSEMBLE}[$e]->{HEADING} ");
-		print(P "$dta{ENSEMBLE}[$e]->{PITCH} ");
-		print(P "$dta{ENSEMBLE}[$e]->{ROLL} ");
+		print(P defined($dta{ENSEMBLE}[$e]->{HEADING}) ? "$dta{ENSEMBLE}[$e]->{HEADING} " : 'nan ');
+		print(P defined($dta{ENSEMBLE}[$e]->{PITCH}) ? "$dta{ENSEMBLE}[$e]->{PITCH} " : 'nan ');
+		print(P defined($dta{ENSEMBLE}[$e]->{ROLL}) ? "$dta{ENSEMBLE}[$e]->{ROLL} " : 'nan ');
 		print(P "$dta{ENSEMBLE}[$e]->{HEADING_STDDEV} ");
 		print(P "$dta{ENSEMBLE}[$e]->{PITCH_STDDEV} ");
 		print(P "$dta{ENSEMBLE}[$e]->{ROLL_STDDEV} ");
@@ -250,8 +252,10 @@
 	next if (defined($first_ens) &&
 			 $dta{ENSEMBLE}[$e]->{NUMBER} < $first_ens);
 
-	$dta{ENSEMBLE}[$e]->{PITCH} -= $P{pitch_bias};
-	$dta{ENSEMBLE}[$e]->{ROLL}  -= $P{roll_bias};
+	$dta{ENSEMBLE}[$e]->{PITCH} -= $P{pitch_bias}
+		if defined($dta{ENSEMBLE}[$e]->{PITCH});
+	$dta{ENSEMBLE}[$e]->{ROLL}  -= $P{roll_bias}
+		if defined($dta{ENSEMBLE}[$e]->{ROLL});
 
 	$P{first_ens} = $dta{ENSEMBLE}[$e]->{NUMBER},$fe = $e
 		unless defined($P{first_ens});
--- a/listEns
+++ b/listEns
@@ -2,9 +2,9 @@
 #======================================================================
 #                    L I S T E N S 
 #                    doc: Sat Jan 18 18:41:49 2003
-#                    dlm: Wed Aug  7 10:38:17 2013
+#                    dlm: Tue Mar  4 12:56:36 2014
 #                    (c) 2003 A.M. Thurnherr
-#                    uE-Info: 215 0 NIL 0 0 72 2 2 4 NIL ofnI
+#                    uE-Info: 46 64 NIL 0 0 72 2 2 4 NIL ofnI
 #======================================================================
 
 # Print useful info from the ensemble list or dump ensembles to
@@ -42,6 +42,8 @@
 #				  - 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
 
 # Notes:
 #	- -E outputs data in earth coordinates, unless -b is set also
@@ -134,14 +136,19 @@
 		{
 			my($e) = @_;
 			
-			printf('%d %lf %d %g %g %g %g %g %g',
+			printf('%d %lf %d %g',
 				$dta{ENSEMBLE}[$e]->{NUMBER},
 				$dta{ENSEMBLE}[$e]->{UNIX_TIME},
 				$dta{ENSEMBLE}[$e]->{XDUCER_FACING_UP} ? 1 : 0,
 				$dta{ENSEMBLE}[$e]->{TEMPERATURE},
-				$dta{ENSEMBLE}[$e]->{HEADING},
-				$dta{ENSEMBLE}[$e]->{PITCH},
-				$dta{ENSEMBLE}[$e]->{ROLL},
+			);
+			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},
 			);
@@ -244,10 +251,10 @@
 	} else {											# neither ANTS nor ens files
 		unless ($opt_Q) {
 			if ($dta{FIXED_LEADER_BYTES} >= 53) {
-				printf("    # Date       Time        XD  Temp Headng Pitch  Roll vels(bin1) ESW$addLayout\n");
+				printf("    # Date       Time        XD  Temp Headng Pitch  Roll #vv DSID ESW$addLayout\n");
 				printf("-----------------------------------------------------------------------\n");
 			} else {
-				printf("    # Date       Time        XD  Temp Headng Pitch  Roll vels(bin1)$addLayout\n");
+				printf("    # Date       Time        XD  Temp Headng Pitch  Roll #vv DSID$addLayout\n");
 				printf("-------------------------------------------------------------------\n");
 			}
 		}
@@ -256,16 +263,22 @@
 		{
 			my($e) = @_;
 
-			printf('%5d %s %s %s %5.1f %6.1f %5.1f %5.1f %3d',
+			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},
-				$dta{ENSEMBLE}[$e]->{HEADING},
-				$dta{ENSEMBLE}[$e]->{PITCH},
-				$dta{ENSEMBLE}[$e]->{ROLL},
+			);
+			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);
--- a/listHdr
+++ b/listHdr
@@ -2,9 +2,9 @@
 #======================================================================
 #                    L I S T H D R 
 #                    doc: Sat Jan 18 18:41:49 2003
-#                    dlm: Mon Mar 25 19:20:19 2013
+#                    dlm: Thu Apr 24 14:50:23 2014
 #                    (c) 2003 A.M. Thurnherr
-#                    uE-Info: 79 0 NIL 0 0 72 8 2 4 NIL ofnI
+#                    uE-Info: 33 81 NIL 0 0 72 8 2 4 NIL ofnI
 #======================================================================
 
 # Print useful info from the RDI BB header
@@ -30,6 +30,7 @@
 #	Jul  9, 2008: - added output regarding available sensors
 #	Mar 20, 2013: - removed DATA_FORMAT stuff
 #	Mar 25, 2013: - added INSTRUMENT_TYPE stuff instead
+#	Apr 24, 2014: - BUG: USE_3_BEAM_ON_LOW_CORR was reported in water-track setup
 
 $0 =~ m{(.*/)[^/]+};
 require "$1RDI_BB_Read.pl";
@@ -103,6 +104,7 @@
 	printf("EARTH_COORDINATES ")				if ($hdr{EARTH_COORDINATES});
 	printf("PITCH_AND_ROLL_USED ")				if ($hdr{PITCH_AND_ROLL_USED});
 	printf("BIN_MAPPING_ALLOWED ")				if ($hdr{ALLOW_BIN_MAPPING});
+	printf("USE_3_BEAM_ON_LOW_CORR ")			if ($hdr{USE_3_BEAM_ON_LOW_CORR});
 	print("\n");
 	
 	
@@ -149,7 +151,6 @@
 	printf("NARROW_BANDWIDTH ") 				if ($hdr{NARROW_BANDWIDTH});
 	printf("WIDE_BANDWIDTH ")					if ($hdr{WIDE_BANDWIDTH});
 	printf("TRANSMIT_POWER_HIGH ")				if ($hdr{TRANSMIT_POWER_HIGH});
-	printf("USE_3_BEAM_ON_LOW_CORR ")			if ($hdr{USE_3_BEAM_ON_LOW_CORR});
 	print("\n");
 
 #----------------------------------------------------------------------
--- a/mkProfile
+++ b/mkProfile
@@ -2,9 +2,9 @@
 #======================================================================
 #                    M K P R O F I L E 
 #                    doc: Sun Jan 19 18:55:26 2003
-#                    dlm: Thu Feb 13 15:45:20 2014
+#                    dlm: Sat May 24 22:50:02 2014
 #                    (c) 2003 A.M. Thurnherr
-#                    uE-Info: 283 0 NIL 0 0 72 2 2 4 NIL ofnI
+#                    uE-Info: 797 76 NIL 0 0 72 10 2 4 NIL ofnI
 #======================================================================
 
 # Make an LADCP Profile by Integrating W (similar to Firing's scan*).
@@ -85,6 +85,9 @@
 #				  - finally removed -d/-g
 #	Nov 25, 2013: - expunged checkEnsemble
 #	Feb 13, 2014: - added support set_range_lim()
+#	Mar  4, 2014: - added support to allow missing PITCH/ROLL/HEADING values
+#	May 24, 2014: - finally added (gimbal-)pitch & roll to default output
+#				  - renamed heading to hdg and pitchroll to tilt
 
 # NOTES:
 #	- the battery values are based on transmission voltages (different
@@ -564,12 +567,19 @@
 # Step 6: Pitch, Roll, Rotation
 #======================================================================
 
+# in case of PITCH/ROLL/HEADING data gaps (IMP data), the calculations
+# are not entirely correct, as
+# 	i)  the rotation implied by the pre-/post-gap headings is not counted
+#	ii) the gappy ensembles are counted for calculating the rms vals
+
 my($prrms,$dnprrms,$upprrms) = (0,0,0);
 my($rotrms,$prerot,$dnrot,$uprot,$postrot) = (0,0,0,0,0);
 
 sub rot($)
 {
 	my($e) = @_;
+	return 0
+		unless defined($dta{ENSEMBLE}[$e]->{HEADING}) && defined($dta{ENSEMBLE}[$e-1]->{HEADING});
 	my($rot) = $dta{ENSEMBLE}[$e]->{HEADING} -
 			   $dta{ENSEMBLE}[$e-1]->{HEADING};
 	$rot -= 360 if ($rot >  180);
@@ -582,10 +592,11 @@
 }
 
 for (; $e<= $atbottom; $e++) {					# downcast
-	$dta{ENSEMBLE}[$e]->{PITCHROLL} =
+	$dta{ENSEMBLE}[$e]->{TILT} =
 		&angle_from_vertical($dta{ENSEMBLE}[$e]->{PITCH},
 						  	 $dta{ENSEMBLE}[$e]->{ROLL});
-	$prrms += $dta{ENSEMBLE}[$e]->{PITCHROLL}**2;
+	$prrms += $dta{ENSEMBLE}[$e]->{TILT}**2
+		if numberp($dta{ENSEMBLE}[$e]->{TILT});
 				 
 	$dta{ENSEMBLE}[$e]->{ROTATION} = rot($e);
 	$dnrot += $dta{ENSEMBLE}[$e]->{ROTATION};
@@ -594,10 +605,11 @@
 $dnprrms = $prrms;
 
 for (; $e<=$lastgood; $e++) {					# upcast
-	$dta{ENSEMBLE}[$e]->{PITCHROLL} =
+	$dta{ENSEMBLE}[$e]->{TILT} =
 		&angle_from_vertical($dta{ENSEMBLE}[$e]->{PITCH},
 						  	 $dta{ENSEMBLE}[$e]->{ROLL});
-	$prrms += $dta{ENSEMBLE}[$e]->{PITCHROLL}**2;
+	$prrms += $dta{ENSEMBLE}[$e]->{TILT}**2
+		if numberp($dta{ENSEMBLE}[$e]->{TILT});
 				 
 	$dta{ENSEMBLE}[$e]->{ROTATION} = rot($e);
 	$uprot += $dta{ENSEMBLE}[$e]->{ROTATION};
@@ -689,7 +701,7 @@
 	if defined($opt_M);
 print("#ANTS#FIELDS# {ens} {time} {elapsed} {secno} {downcast} " .
 					"{w} {w_err} {err_vel} {depth} {depth_err} {seabed} " .
-					"{pitchroll} {heading} {rotation} " .
+					"{pitch} {roll} {tilt} {hdg} {rotation} " .
 					"$uFields $addFields\n");
 
 printf("#ANTS#PARAMS# date{$dta{ENSEMBLE}[$firstgood]->{DATE}} " .
@@ -704,18 +716,18 @@
 		  "0.8_valid_range{%.1f} " .
 				"max_depth{%.1f} " .
 			  "depth_error{%.1f} " .
-				"min_range{%d} " .
-			  "n_ensembles{%d} " .
-			   "w_gap_time{%d} " .
+				  "min_range{%d} " .
+				"n_ensembles{%d} " .
+                 "w_gap_time{%d} " .
 				 "stderr_w{%.4f} " .
-			"rms_pitchroll{%.1f} " .
-   "downcast_rms_pitchroll{%.1f} " .
-	 "upcast_rms_pitchroll{%.1f} " .
+				 "rms_tilt{%.1f} " .
+		"downcast_rms_tilt{%.1f} " .
+          "upcast_rms_tilt{%.1f} " .
 			 "rms_rotation{%.2f} " .
-	 "deployment_rotations{%d} " .
-	   "downcast_rotations{%d} " .
-		 "upcast_rotations{%d} " .
-	   "recovery_rotations{%d} " .
+	   "deployment_rotations{%d} " .
+		 "downcast_rotations{%d} " .
+		   "upcast_rotations{%d} " .
+         "recovery_rotations{%d} " .
    "rms_heave_acceleration{%.2f} " .
 				"bin1_dist{%.1f} " .
 			   "bin_length{%.1f} " .
@@ -782,7 +794,9 @@
 	p($dta{ENSEMBLE}[$e]->{DEPTH});
 	p($dta{ENSEMBLE}[$e]->{DEPTH_ERR});
 	p($dta{ENSEMBLE}[$e]->{seabed});
-	p($dta{ENSEMBLE}[$e]->{PITCHROLL});
+	p(&gimbal_pitch($dta{ENSEMBLE}[$e]->{PITCH},$dta{ENSEMBLE}[$e]->{ROLL}));
+	p($dta{ENSEMBLE}[$e]->{ROLL});
+	p($dta{ENSEMBLE}[$e]->{TILT});
 	p($dta{ENSEMBLE}[$e]->{HEADING});
 	p($dta{ENSEMBLE}[$e]->{ROTATION});
 	if (defined($opt_M)) {
--- a/splitRDI
+++ b/splitRDI
@@ -2,9 +2,9 @@
 #======================================================================
 #                    S P L I T R D I 
 #                    doc: Sat Aug 21 22:20:27 2010
-#                    dlm: Thu Feb 13 14:42:02 2014
+#                    dlm: Wed Mar 19 16:35:45 2014
 #                    (c) 2010 A.M. Thurnherr
-#                    uE-Info: 19 0 NIL 0 0 72 2 2 4 NIL ofnI
+#                    uE-Info: 36 43 NIL 0 0 72 2 2 4 NIL ofnI
 #======================================================================
 
 # split RDI files based on list of ensemble numbers (e.g. from yoyo -t)
@@ -13,6 +13,7 @@
 #	Aug 21, 2010: - created
 #	Jun 24, 2011: - replaced -b, -n by -o
 #   Feb 13, 2014: - updated doc
+#	Mar 19, 2014: - added -s)kip small files
 
 # NOTES:
 #   - it is assumed that the input file begins with ensemble #1
@@ -32,13 +33,16 @@
 
 die("Usage: $0 " .
 	"[-o)ut-file <fmt[e.g. 017%02dDL000.000]>] " .
+	"[require -m)in <ens> to produce output] " .
 	"<RDI file> <ens> <ens[...]>\n")
-		unless (&getopts('o:') && @ARGV>=3);
+		unless (&getopts('o:m:') && @ARGV>=3);
 
 $opt_o = substr($ARGV[0],0,3)					# default output filename format
 		 . '%02d'
 		 . substr($ARGV[0],-9)
 			unless defined($opt_o);
+
+$opt_m = 0 unless defined($opt_m);				# default: produce tiny files as well
 	
 readHeader($ARGV[0],\%hdr); shift;				# get length of ensembles
 $ens_len = $hdr{ENSEMBLE_BYTES} + 2;
@@ -48,19 +52,21 @@
 $cnr = 0;
 
 do {											# split data
-	sysseek(WBRF,($first_ens-2)*$ens_len,0) ||
+	sysseek(WBRF,($first_ens-2)*$ens_len,0) ||	# read next block of data
 		die("$WBRcfn: $!");
 	$last_ens++ unless defined($ARGV[0]);
 	$nBytes = ($last_ens-$first_ens+1) * $ens_len;
 	sysread(WBRF,$buf,$nBytes) == $nBytes ||
 		die("$WBRcfn: file truncated");
 
-	$fn = sprintf($opt_o,$cnr++);
-	open(F,">$fn") || die("$fn: $!\n");
-	syswrite(F,$buf,$nBytes) == $nBytes ||
-		die("$fn: $!\n");
-	close(F);
-	printf(STDERR "$fn: %d ensembles ($nBytes bytes)\n",$last_ens-$first_ens+1);
+	if ($last_ens-$first_ens+1 > $opt_m) {		# produce file only if sufficient # of ensembles
+		$fn = sprintf($opt_o,$cnr++);
+		open(F,">$fn") || die("$fn: $!\n");
+		syswrite(F,$buf,$nBytes) == $nBytes ||
+			die("$fn: $!\n");
+		close(F);
+	    printf(STDERR "$fn: %d ensembles ($nBytes bytes)\n",$last_ens-$first_ens+1);
+	}
 	
 	$first_ens = $last_ens+1;
 	$last_ens  = $ARGV[0]; shift;