RDI_PD0_IO.pl
changeset 31 b6ca27a1d19c
parent 29 aeb26e966b71
child 32 7155adf61d77
equal deleted inserted replaced
30:184133e916be 31:b6ca27a1d19c
     1 #======================================================================
     1 #======================================================================
     2 #                    R D I _ P D 0 _ I O . P L 
     2 #                    R D I _ P D 0 _ I O . P L 
     3 #                    doc: Sat Jan 18 14:54:43 2003
     3 #                    doc: Sat Jan 18 14:54:43 2003
     4 #                    dlm: Sat Jan  9 13:22:46 2016
     4 #                    dlm: Sat Jan  9 17:57:01 2016
     5 #                    (c) 2003 A.M. Thurnherr
     5 #                    (c) 2003 A.M. Thurnherr
     6 #                    uE-Info: 70 34 NIL 0 0 72 2 2 4 NIL ofnI
     6 #                    uE-Info: 73 64 NIL 0 0 72 10 2 4 NIL ofnI
     7 #======================================================================
     7 #======================================================================
     8 
     8 
     9 # Read RDI BroadBand Binary Data Files (*.[0-9][0-9][0-9])
     9 # Read RDI BroadBand Binary Data Files (*.[0-9][0-9][0-9])
    10 
    10 
    11 # HISTORY:
    11 # HISTORY:
    64 #					incomplete ensemble at the end, which seems to imply that there is
    64 #					incomplete ensemble at the end, which seems to imply that there is
    65 #				    a garbage final ensemble that passes the checksum test???
    65 #				    a garbage final ensemble that passes the checksum test???
    66 #	Oct  2, 2015: - added &skip_initial_trash()
    66 #	Oct  2, 2015: - added &skip_initial_trash()
    67 #	Dec 18, 2015: - added most data types to WBPofs()
    67 #	Dec 18, 2015: - added most data types to WBPofs()
    68 #				  - BUG: WBPens() requires round() for scaled values
    68 #				  - BUG: WBPens() requires round() for scaled values
    69 #	Jan  9, 2016: - BUG: WBRhdr() did not set DATA_SOURCE_ID
    69 #	Jan  9, 2016: - removed system() from writeData()
       
    70 #				  - BUG: WBRhdr() did not set DATA_SOURCE_ID
    70 #				  - added PRODUCER
    71 #				  - added PRODUCER
       
    72 #				  - BUG: writeData() did not work correctly for ECOGIG OC26 moored data (spaces in filename?)
       
    73 #				  - added support for patching coordinate system
    71 
    74 
    72 # FIRMWARE VERSIONS:
    75 # FIRMWARE VERSIONS:
    73 #	It appears that different firmware versions generate different file
    76 #	It appears that different firmware versions generate different file
    74 #	structures. Currently (Sep 2005) these routines have been tested
    77 #	structures. Currently (Sep 2005) these routines have been tested
    75 #	with the following firmware versions (as reported by [listHdr]):
    78 #	with the following firmware versions (as reported by [listHdr]):
    90 #		PATCHED_MASK & 0x02:						roll value has been patched
    93 #		PATCHED_MASK & 0x02:						roll value has been patched
    91 #		PATCHED_MASK & 0x01:						heading value has been patched
    94 #		PATCHED_MASK & 0x01:						heading value has been patched
    92 #			- PITCH & ROLL can be missing (0x8000 badval as in velocities)
    95 #			- PITCH & ROLL can be missing (0x8000 badval as in velocities)
    93 #			- HEADING can be missing (0xF000 badval, as 0x8000 is valid 327.68 heading)
    96 #			- HEADING can be missing (0xF000 badval, as 0x8000 is valid 327.68 heading)
    94 #
    97 #
    95 #	- DATA_SOURCE_ID = 0xB0 					produced by editPD0
    98 #	- DATA_SOURCE_ID = 0xE0 					produced by editPD0
    96 
    99 
    97 # NOTES:
   100 # NOTES:
    98 #	- RDI stores data in VAX/Intel byte order (little endian)
   101 #	- RDI stores data in VAX/Intel byte order (little endian)
    99 #	- the output data structure does not exactly mirror the file data
   102 #	- the output data structure does not exactly mirror the file data
   100 #	  structure; the header is not stored at all and the fixed leader
   103 #	  structure; the header is not stored at all and the fixed leader
   331 	while ($found < 2) {
   334 	while ($found < 2) {
   332 		sysread(WBRF,$buf,1) == 1 || last;
   335 		sysread(WBRF,$buf,1) == 1 || last;
   333 		($dta) = unpack('C',$buf);
   336 		($dta) = unpack('C',$buf);
   334 		if ($dta == 0x7f) {
   337 		if ($dta == 0x7f) {
   335 			$found++;
   338 			$found++;
       
   339 		} elsif ($found==1 && ($dta==0xE0 || ($dta&0xF0==0xA0 && $dta&0x0F<8))) {
       
   340 			$found++;
   336 		} elsif ($found == 0) {
   341 		} elsif ($found == 0) {
   337 			$skipped++;
   342 			$skipped++;
   338 		} else {
   343 		} else {
   339 			$skipped += $found;
   344 			$skipped += $found;
   340 			$found = 0;
   345 			$found = 0;
   377 		= unpack('CCvCC',$buf);
   382 		= unpack('CCvCC',$buf);
   378 	$hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header",$hid,0));
   383 	$hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header",$hid,0));
   379 	$dta->{DATA_SOURCE_ID} = $did;
   384 	$dta->{DATA_SOURCE_ID} = $did;
   380 	if ($did == 0x7f) {
   385 	if ($did == 0x7f) {
   381 		$dta->{PRODUCER} = 'TRDI ADCP';
   386 		$dta->{PRODUCER} = 'TRDI ADCP';
   382 	} elsif ($did&0xF0 == 0xA0) {
   387 	} elsif (($did&0xF0) == 0xA0) {
   383 		$dta->{PRODUCER} = 'IMP+LADCP';
   388 		$dta->{PRODUCER} = 'IMP+LADCP (Thurnherr software)';
   384 	} elsif ($did&0xF0 == 0xB0) {
   389 	} elsif (($did&0xF0) == 0xE0) {
   385 		$dta->{PRODUCER} = 'editPD0';
   390 		$dta->{PRODUCER} = 'editPD0 (Thurnherr software)';
   386 	} else {
   391 	} else {
   387 		$dta->{PRODUCER} = 'unknown';
   392 		$dta->{PRODUCER} = sprintf('unknown (0x%02X)');
   388 	}
   393 	}
   389 
   394 
   390 	printf(STDERR "WARNING: unexpected number of data types (%d)\n",
   395 	printf(STDERR "WARNING: unexpected number of data types (%d)\n",
   391 		$dta->{NUMBER_OF_DATA_TYPES})
   396 		$dta->{NUMBER_OF_DATA_TYPES})
   392 			unless ($dta->{NUMBER_OF_DATA_TYPES} == 6 ||
   397 			unless ($dta->{NUMBER_OF_DATA_TYPES} == 6 ||
   650 		${$E}[$ens]->{DATA_SOURCE_ID} = $did;
   655 		${$E}[$ens]->{DATA_SOURCE_ID} = $did;
   651 		if ($did == 0x7f) {
   656 		if ($did == 0x7f) {
   652 			${$E}[$ens]->{PRODUCER} = 'TRDI ADCP';
   657 			${$E}[$ens]->{PRODUCER} = 'TRDI ADCP';
   653 		} elsif ($did&0xF0 == 0xA0) {
   658 		} elsif ($did&0xF0 == 0xA0) {
   654 			${$E}[$ens]->{PRODUCER} = 'IMP+LADCP (Thurnherr software)';
   659 			${$E}[$ens]->{PRODUCER} = 'IMP+LADCP (Thurnherr software)';
   655 		} elsif ($did&0xF0 == 0xB0) {
   660 		} elsif ($did&0xF0 == 0xE0) {
   656 			${$E}[$ens]->{PRODUCER} = 'editPD0 (Thurnherr software)';
   661 			${$E}[$ens]->{PRODUCER} = 'editPD0 (Thurnherr software)';
   657 		} else {
   662 		} else {
   658 			${$E}[$ens]->{PRODUCER} = 'unknown';
   663 			${$E}[$ens]->{PRODUCER} = 'unknown';
   659 	    }
   664 	    }
   660 
   665 
   983 sub writeData(@)
   988 sub writeData(@)
   984 {
   989 {
   985 	my($fn,$dta) = @_;
   990 	my($fn,$dta) = @_;
   986 
   991 
   987 	die("writeData() needs \$WBRcfn from previous readData()")
   992 	die("writeData() needs \$WBRcfn from previous readData()")
   988 		unless (-r $WBRcfn);
   993 		unless (length($WBRcfn) > 0);
   989 	$WBPcfn = $fn;
   994 
   990 	system("cp $WBRcfn $WBPcfn");
   995     sysseek(WBRF,0,0) || die("$WBRcfn: $!");						# rewind input file
   991 
   996 	$WBPcfn = $fn;													# set patch file name for error messages
   992 	open(WBPF,"+<$WBPcfn") || die("$WBPcfn: $!");
   997 	open(WBPF,"+>$WBPcfn") || die("$WBPcfn: $!");					# open patch file for r/w
   993     WBPens($dta->{N_BINS},$dta->{FIXED_LEADER_BYTES},
   998 
   994 	                   \@{$dta->{ENSEMBLE}});
   999 	while (1) {														# copy input file to patch file
       
  1000 		my($buf);
       
  1001 		my($nread) = sysread(WBRF,$buf,100*1024);
       
  1002 		die("$WBRcfn: $!\n") if ($nread < 0);
       
  1003 		last if ($nread == 0);
       
  1004 		my($nwritten) = syswrite(WBPF,$buf,100*1024);
       
  1005 		die("$WBPcfn: $! ($nwritten of $nread written)\n")
       
  1006 			unless ($nwritten = $nread);
       
  1007 	}
       
  1008     sysseek(WBPF,0,0) || die("$WBPcfn: $!");						# rewind patch file
       
  1009 
       
  1010     WBPens($dta->{N_BINS},$dta->{FIXED_LEADER_BYTES},$dta);
   995 }
  1011 }
   996 
  1012 
   997 sub round(@)
  1013 sub round(@)
   998 {
  1014 {
   999 	return $_[0] >= 0 ? int($_[0] + 0.5)
  1015 	return $_[0] >= 0 ? int($_[0] + 0.5)
  1001 }
  1017 }
  1002 
  1018 
  1003 
  1019 
  1004 sub WBPens($$$)
  1020 sub WBPens($$$)
  1005 {
  1021 {
  1006 	my($nbins,$fixed_leader_bytes,$E) = @_;
  1022 	my($nbins,$fixed_leader_bytes,$dta) = @_;
  1007 	my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBPofs);
  1023 	my($start_ens,$B1,$B2,$B3,$B4,$I,$id,$bin,$beam,$buf,$dummy,@dta,$i,$cs,@WBPofs);
  1008 	my($ens,$ensNo,$dayStart,$ens_length,$hid,$ndt);
  1024 	my($ens,$ensNo,$dayStart,$ens_length,$hid,$ndt);
  1009 
  1025 
  1010 	for ($ens=$start_ens=0; $ens<=$#{$E}; $ens++,$start_ens+=$ens_length+2) {
  1026 	for ($ens=$start_ens=0; $ens<=$#{$dta->{ENSEMBLE}}; $ens++,$start_ens+=$ens_length+2) {
  1011 
  1027 
  1012 		#------------------------------
  1028 		#------------------------------
  1013 		# Patch Header (Data Source Id)
  1029 		# Patch Header (Data Source Id)
  1014 		#------------------------------
  1030 		#------------------------------
  1015 
  1031 
  1016 		sysseek(WBPF,$start_ens,0) || die("$WBPcfn: $!");
  1032 		sysseek(WBPF,$start_ens,0) || die("$WBPcfn: $!");
  1017 		sysread(WBPF,$buf,1) || die("$WBPcfn: unexpected EOF");
  1033 		sysread(WBPF,$buf,1) || die("$WBPcfn: unexpected EOF");
  1018 		($hid) = unpack('C',$buf);
  1034 		($hid) = unpack('C',$buf);
  1019 		$hid == 0x7f || die(sprintf($FmtErr,$WBPcfn,"Header",$hid,$ens));
  1035 		$hid == 0x7f || die(sprintf($FmtErr,$WBPcfn,"Header",$hid,$ens));
  1020 
  1036 
  1021 		$buf = pack('C',${$E}[$ens]->{DATA_SOURCE_ID});
  1037 		$buf = pack('C',$dta->{ENSEMBLE}[$ens]->{DATA_SOURCE_ID});
  1022 		my($nw) = syswrite(WBPF,$buf,1);
  1038 		my($nw) = syswrite(WBPF,$buf,1);
  1023 		$nw == 1 || die("$WBPcfn: $nw bytes written ($!)");
  1039 		$nw == 1 || die("$WBPcfn: $nw bytes written ($!)");
  1024 
  1040 
  1025 		sysread(WBPF,$buf,4) == 4 || die("$WBPcfn: unexpected EOF");
  1041 		sysread(WBPF,$buf,4) == 4 || die("$WBPcfn: unexpected EOF");
  1026 		($ens_length,$dummy,$ndt) = unpack('vCC',$buf);
  1042 		($ens_length,$dummy,$ndt) = unpack('vCC',$buf);
  1028 				unless ($ndt == 6 || $ndt == 7);
  1044 				unless ($ndt == 6 || $ndt == 7);
  1029 
  1045 
  1030 		sysread(WBPF,$buf,2*$ndt) == 2*$ndt || die("$WBPcfn: $!");
  1046 		sysread(WBPF,$buf,2*$ndt) == 2*$ndt || die("$WBPcfn: $!");
  1031 		@WBPofs = unpack("v$ndt",$buf);
  1047 		@WBPofs = unpack("v$ndt",$buf);
  1032 		$fixed_leader_bytes = $WBPofs[1] - $WBPofs[0];
  1048 		$fixed_leader_bytes = $WBPofs[1] - $WBPofs[0];
       
  1049 
       
  1050 		#--------------------
       
  1051 		# Fixed Leader
       
  1052 		#--------------------
  1033 	
  1053 	
       
  1054 		sysseek(WBPF,$start_ens+$WBPofs[0]+25,0) || die("$WBPcfn: $!");		# jump to EX/Coord-Transform
       
  1055 		sysread(WBPF,$buf,1) == 1 || die("$WBPcfn: $!");
       
  1056 		my($EX) = unpack('C',$buf);
       
  1057 		if ($dta->{BEAM_COORDINATES}) {
       
  1058 			$EX &= ~0x18;
       
  1059 		} elsif ($dta->{EARTH_COORDINATES}) {
       
  1060 			$EX |= 0x18;
       
  1061 		} else {
       
  1062 			die("$WBPcfn: only beam- and earth coordinates are supported (implementation restriction)\n");
       
  1063 		}
       
  1064 		$buf = pack('C',$EX);		
       
  1065 		sysseek(WBPF,$start_ens+$WBPofs[0]+25,0) || die("$WBPcfn: $!");
       
  1066 		syswrite(WBPF,$buf,1) == 1 || die("$WBPcfn: $!");
       
  1067 
  1034 		#------------------------------
  1068 		#------------------------------
  1035 		# Variable Leader
  1069 		# Variable Leader
  1036 		#------------------------------
  1070 		#------------------------------
  1037 	
  1071 
  1038 		sysseek(WBPF,$start_ens+$WBPofs[1]+12,0) || die("$WBPcfn: $!");
  1072 		sysseek(WBPF,$start_ens+$WBPofs[1]+14,0) || die("$WBPcfn: $!");		# jump to SPEED_OF_SOUND
  1039 		
  1073 		
  1040 		${$E}[$ens]->{XDUCER_DEPTH} = round(${$E}[$ens]->{XDUCER_DEPTH}*10);
  1074 		$dta->{ENSEMBLE}[$ens]->{XDUCER_DEPTH} = round($dta->{ENSEMBLE}[$ens]->{XDUCER_DEPTH}*10);
  1041 
  1075 
  1042 		#-----------------------------
  1076 		#-----------------------------
  1043 		# IMP allows for missing value
  1077 		# IMP allows for missing value
  1044 		#-----------------------------
  1078 		#-----------------------------
  1045 
  1079 
  1046 		${$E}[$ens]->{HEADING} = defined(${$E}[$ens]->{HEADING})
  1080 		$dta->{ENSEMBLE}[$ens]->{HEADING} = defined($dta->{ENSEMBLE}[$ens]->{HEADING})
  1047 							   ? round(${$E}[$ens]->{HEADING}*100)
  1081 							   ? round($dta->{ENSEMBLE}[$ens]->{HEADING}*100)
  1048 							   : 0xF000;
  1082 							   : 0xF000;
  1049 		${$E}[$ens]->{PITCH} = defined(${$E}[$ens]->{PITCH})
  1083 		$dta->{ENSEMBLE}[$ens]->{PITCH} = defined($dta->{ENSEMBLE}[$ens]->{PITCH})
  1050 							 ? unpack('S',pack('s',round(${$E}[$ens]->{PITCH}*100)))
  1084 							 ? unpack('S',pack('s',round($dta->{ENSEMBLE}[$ens]->{PITCH}*100)))
  1051 							 : 0x8000;
  1085 							 : 0x8000;
  1052 		${$E}[$ens]->{ROLL} = defined(${$E}[$ens]->{ROLL})
  1086 		$dta->{ENSEMBLE}[$ens]->{ROLL} = defined($dta->{ENSEMBLE}[$ens]->{ROLL})
  1053 						    ? unpack('S',pack('s',round(${$E}[$ens]->{ROLL}*100)))
  1087 						    ? unpack('S',pack('s',round($dta->{ENSEMBLE}[$ens]->{ROLL}*100)))
  1054 						    : 0x8000;
  1088 						    : 0x8000;
  1055 
  1089 
  1056 		${$E}[$ens]->{TEMPERATURE} =
  1090 		$dta->{ENSEMBLE}[$ens]->{TEMPERATURE} =
  1057 			unpack('S',pack('s',round(${$E}[$ens]->{TEMPERATURE}*100)));
  1091 			unpack('S',pack('s',round($dta->{ENSEMBLE}[$ens]->{TEMPERATURE}*100)));
  1058 
       
  1059 		sysseek(WBPF,2,1);			# skip built-in test which reads as 0 but is usually undef		
       
  1060 									# this was found not to matter, but there is no reason to edit
       
  1061 #		my($b1);					# this field
       
  1062 #		sysread(WBPF,$b1,14);
       
  1063 #		sysseek(WBPF,-14,1);
       
  1064 #		my($sos,$xd,$hdg,$pit,$rol,$sal,$tem) = unpack('vvvvvvv',$b1);
       
  1065 
  1092 
  1066 		$buf = pack('vvvvvvv',
  1093 		$buf = pack('vvvvvvv',
  1067 			 ${$E}[$ens]->{SPEED_OF_SOUND},
  1094 			 $dta->{ENSEMBLE}[$ens]->{SPEED_OF_SOUND},
  1068 			 ${$E}[$ens]->{XDUCER_DEPTH},${$E}[$ens]->{HEADING},
  1095 			 $dta->{ENSEMBLE}[$ens]->{XDUCER_DEPTH},$dta->{ENSEMBLE}[$ens]->{HEADING},
  1069 			 ${$E}[$ens]->{PITCH},${$E}[$ens]->{ROLL},
  1096 			 $dta->{ENSEMBLE}[$ens]->{PITCH},$dta->{ENSEMBLE}[$ens]->{ROLL},
  1070 			 ${$E}[$ens]->{SALINITY},${$E}[$ens]->{TEMPERATURE});
  1097 			 $dta->{ENSEMBLE}[$ens]->{SALINITY},$dta->{ENSEMBLE}[$ens]->{TEMPERATURE});
  1071 
  1098 
  1072 		my($nw) = syswrite(WBPF,$buf,14);
  1099 		my($nw) = syswrite(WBPF,$buf,14);
  1073 		$nw == 14 || die("$WBPcfn: $nw bytes written ($!)");
  1100 		$nw == 14 || die("$WBPcfn: $nw bytes written ($!)");
  1074 
  1101 
  1075 
  1102 
  1078 		#--------------------
  1105 		#--------------------
  1079 
  1106 
  1080 		sysseek(WBPF,$start_ens+$WBPofs[2]+2,0) || die("$WBRcfn: $!");	# skip velocity data id (assume it is correct)
  1107 		sysseek(WBPF,$start_ens+$WBPofs[2]+2,0) || die("$WBRcfn: $!");	# skip velocity data id (assume it is correct)
  1081 		for ($bin=0; $bin<$nbins; $bin++) {
  1108 		for ($bin=0; $bin<$nbins; $bin++) {
  1082 			for ($beam=0; $beam<4; $beam++) {
  1109 			for ($beam=0; $beam<4; $beam++) {
  1083 				${$E}[$ens]->{VELOCITY}[$bin][$beam] = defined(${$E}[$ens]->{VELOCITY}[$bin][$beam])
  1110 				$dta->{ENSEMBLE}[$ens]->{VELOCITY}[$bin][$beam] = defined($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$bin][$beam])
  1084 							   						 ? round(${$E}[$ens]->{VELOCITY}[$bin][$beam]*1000)
  1111 							   						 ? round($dta->{ENSEMBLE}[$ens]->{VELOCITY}[$bin][$beam]*1000)
  1085 							   						 : 0x8000;
  1112 							   						 : 0x8000;
  1086 				$buf = pack('v',unpack('S',pack('s',${$E}[$ens]->{VELOCITY}[$bin][$beam])));
  1113 				$buf = pack('v',unpack('S',pack('s',$dta->{ENSEMBLE}[$ens]->{VELOCITY}[$bin][$beam])));
  1087 				my($nw) = syswrite(WBPF,$buf,2);
  1114 				my($nw) = syswrite(WBPF,$buf,2);
  1088 				$nw == 2 || die("$WBPcfn: $nw bytes written ($!)");
  1115 				$nw == 2 || die("$WBPcfn: $nw bytes written ($!)");
  1089 			}
  1116 			}
  1090 		}
  1117 		}
  1091 
  1118 
  1094 		#--------------------
  1121 		#--------------------
  1095 
  1122 
  1096 		sysseek(WBPF,$start_ens+$WBPofs[3]+2,0) || die("$WBRcfn: $!");
  1123 		sysseek(WBPF,$start_ens+$WBPofs[3]+2,0) || die("$WBRcfn: $!");
  1097 		for ($bin=0; $bin<$nbins; $bin++) {
  1124 		for ($bin=0; $bin<$nbins; $bin++) {
  1098 			for ($beam=0; $beam<4; $beam++) {
  1125 			for ($beam=0; $beam<4; $beam++) {
  1099 				$buf = pack('C',${$E}[$ens]->{CORRELATION}[$bin][$beam]);
  1126 				$buf = pack('C',$dta->{ENSEMBLE}[$ens]->{CORRELATION}[$bin][$beam]);
  1100 				my($nw) = syswrite(WBPF,$buf,1);
  1127 				my($nw) = syswrite(WBPF,$buf,1);
  1101 				$nw == 1 || die("$WBPcfn: $nw bytes written ($!)");
  1128 				$nw == 1 || die("$WBPcfn: $nw bytes written ($!)");
  1102 			}
  1129 			}
  1103 		}
  1130 		}
  1104 
  1131 
  1108 
  1135 
  1109 		sysseek(WBPF,$start_ens+$WBPofs[4]+2,0) || die("$WBRcfn: $!");
  1136 		sysseek(WBPF,$start_ens+$WBPofs[4]+2,0) || die("$WBRcfn: $!");
  1110 
  1137 
  1111 		for ($bin=0; $bin<$nbins; $bin++) {
  1138 		for ($bin=0; $bin<$nbins; $bin++) {
  1112 			for ($beam=0; $beam<4; $beam++) {
  1139 			for ($beam=0; $beam<4; $beam++) {
  1113 				$buf = pack('C',${$E}[$ens]->{ECHO_AMPLITUDE}[$bin][$beam]);
  1140 				$buf = pack('C',$dta->{ENSEMBLE}[$ens]->{ECHO_AMPLITUDE}[$bin][$beam]);
  1114 				my($nw) = syswrite(WBPF,$buf,1);
  1141 				my($nw) = syswrite(WBPF,$buf,1);
  1115 				$nw == 1 || die("$WBPcfn: $nw bytes written ($!)");
  1142 				$nw == 1 || die("$WBPcfn: $nw bytes written ($!)");
  1116 			}
  1143 			}
  1117 		}
  1144 		}
  1118 
  1145 
  1122 
  1149 
  1123 		sysseek(WBPF,$start_ens+$WBPofs[5]+2,0) || die("$WBRcfn: $!");
  1150 		sysseek(WBPF,$start_ens+$WBPofs[5]+2,0) || die("$WBRcfn: $!");
  1124 
  1151 
  1125 		for ($i=0,$bin=0; $bin<$nbins; $bin++) {
  1152 		for ($i=0,$bin=0; $bin<$nbins; $bin++) {
  1126 			for ($beam=0; $beam<4; $beam++,$i++) {
  1153 			for ($beam=0; $beam<4; $beam++,$i++) {
  1127 				$buf = pack('C',${$E}[$ens]->{PERCENT_GOOD}[$bin][$beam]);
  1154 				$buf = pack('C',$dta->{ENSEMBLE}[$ens]->{PERCENT_GOOD}[$bin][$beam]);
  1128 				my($nw) = syswrite(WBPF,$buf,1);
  1155 				my($nw) = syswrite(WBPF,$buf,1);
  1129 				$nw == 1 || die("$WBPcfn: $nw bytes written ($!)");
  1156 				$nw == 1 || die("$WBPcfn: $nw bytes written ($!)");
  1130 			}
  1157 			}
  1131 		}
  1158 		}
  1132 
  1159