RDI_PD0_IO.pl
changeset 50 6bfec705d25e
parent 49 8f4fbdaf0102
child 51 148c092b3a09
equal deleted inserted replaced
49:8f4fbdaf0102 50:6bfec705d25e
     1 #======================================================================
     1 #======================================================================
     2 #                    R D I _ P D 0 _ I O . P L 
     2 #                    / D A T A / S R C / O C E A N O G R A P H Y / A D C P _ T O O L S / R D I _ B B _ R E A D . P L 
     3 #                    doc: Sat Jan 18 14:54:43 2003
     3 #                    doc: Sat Jan 18 14:54:43 2003
     4 #                    dlm: Wed Jun 26 09:27:46 2019
     4 #                    dlm: Thu Feb 27 10:28:29 2020
     5 #                    (c) 2003 A.M. Thurnherr
     5 #                    (c) 2003 A.M. Thurnherr
     6 #					 uE-Info: 645 39 NIL 0 0 72 2 2 4 NIL ofnI
     6 #					 uE-Info: 716 1 NIL 0 0 72 0 2 4 NIL ofnI
     7 #======================================================================
     7 #======================================================================
     8 	
     8 	
     9 # Read RDI PD0 binary data files (*.[0-9][0-9][0-9])
     9 # Read RDI PD0 binary data files (*.[0-9][0-9][0-9])
    10 	
    10 	
    11 # HISTORY:
    11 # HISTORY:
   113 #				  - added warning on wrong ensemble length
   113 #				  - added warning on wrong ensemble length
   114 #	Jun  9, 2018: - removed double \n from warnings
   114 #	Jun  9, 2018: - removed double \n from warnings
   115 #	Jun 12, 2018: - BUG: IMPed files did not pass the garbage detection
   115 #	Jun 12, 2018: - BUG: IMPed files did not pass the garbage detection
   116 #	Jun 13, 2019: - adapted reading routines to RTI files (free order of data types)
   116 #	Jun 13, 2019: - adapted reading routines to RTI files (free order of data types)
   117 #				  - removed old BT_PRESENT code
   117 #				  - removed old BT_PRESENT code
       
   118 #	Jun 28, 2019: - renamed SECONDS to SECOND for consistency
       
   119 #	Jun 30, 2019: - added dirty flag to prevent bad PD0 patching
       
   120 #	Feb 13, 2020: - added support for $readDataProgress
   118 	
   121 	
   119 # FIRMWARE VERSIONS:
   122 # FIRMWARE VERSIONS:
   120 #	It appears that different firmware versions generate different file
   123 #	It appears that different firmware versions generate different file
   121 #	structures. Currently (Sep 2005) these routines have been tested
   124 #	structures. Currently (Sep 2005) these routines have been tested
   122 #	with the following firmware versions (as reported by [listHdr]):
   125 #	with the following firmware versions (as reported by [listHdr]):
   290 #		MONTH						scalar		1--12
   293 #		MONTH						scalar		1--12
   291 #		DAY 						scalar		1--31
   294 #		DAY 						scalar		1--31
   292 #		TIME						string		HH:MM:SS.hh
   295 #		TIME						string		HH:MM:SS.hh
   293 #		HOUR						scalar		0--23
   296 #		HOUR						scalar		0--23
   294 #		MINUTE						scalar		0--59
   297 #		MINUTE						scalar		0--59
   295 #		SECONDS 					scalar		0--59.99
   298 #		SECOND	 					scalar		0--59.99
   296 #		UNIX_TIME					scalar		0--?
   299 #		UNIX_TIME					scalar		0--?
   297 #		SECNO						scalar		0--? (number of seconds since daystart)
   300 #		SECNO						scalar		0--? (number of seconds since daystart)
   298 #		DAYNO						double		fractional day number since start of current year (1.0 is midnight Jan 1st)
   301 #		DAYNO						double		fractional day number since start of current year (1.0 is midnight Jan 1st)
   299 #		VELOCITY[bin][beam] 		scalars 	-32.767--32.768 [m/s], undef=bad
   302 #		VELOCITY[bin][beam] 		scalars 	-32.767--32.768 [m/s], undef=bad
   300 #		CORRELATION[bin][beam]		scalars 	1--255, undefined=bad
   303 #		CORRELATION[bin][beam]		scalars 	1--255, undefined=bad
   450 	#--------------------
   453 	#--------------------
   451 	# HEADER
   454 	# HEADER
   452 	#--------------------
   455 	#--------------------
   453 
   456 
   454 	my($skipped) = goto_next_ens(\*WBRF,1);	
   457 	my($skipped) = goto_next_ens(\*WBRF,1);	
   455    	printf(STDERR "WARNING: %d bytes of initial garbage\n",$skipped)
   458 	if ($skipped > 0) {
   456 		if ($skipped > 0);
   459 		$RDI_PD0_IO::File_Dirty = 1;
       
   460 	   	printf(STDERR "WARNING: %d bytes of initial garbage\n",$skipped);
       
   461 	}
   457 	
   462 	
   458 	sysread(WBRF,$buf,6) == 6 || return undef;
   463 	sysread(WBRF,$buf,6) == 6 || return undef;
   459 	($hid,$did,$dta->{ENSEMBLE_BYTES},$dummy,$dta->{NUMBER_OF_DATA_TYPES})
   464 	($hid,$did,$dta->{ENSEMBLE_BYTES},$dummy,$dta->{NUMBER_OF_DATA_TYPES})
   460 		= unpack('CCvCC',$buf);
   465 		= unpack('CCvCC',$buf);
   461 	$hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header (hid)",$hid,0));
   466 	$hid == 0x7f || die(sprintf($FmtErr,$WBRcfn,"Header (hid)",$hid,0));
   679 #----------------------------------------------------------------------
   684 #----------------------------------------------------------------------
   680 # readData(file_name,^data[,first_ens,last_ens[,last_bin]]) 
   685 # readData(file_name,^data[,first_ens,last_ens[,last_bin]]) 
   681 # 	- read ensembles
   686 # 	- read ensembles
   682 #	- read all ensembles unless first_ens and last_ens are given
   687 #	- read all ensembles unless first_ens and last_ens are given
   683 #	- read all bins unless last_bin is given
   688 #	- read all bins unless last_bin is given
       
   689 #	- if global var $readDataProgress > 0, a . is printed
       
   690 #	  every $readaDataProgress ensembles
   684 #----------------------------------------------------------------------
   691 #----------------------------------------------------------------------
   685 
   692 
   686 sub readData(@)
   693 sub readData(@)
   687 {
   694 {
   688 	my($fn,$dta,$fe,$le,$lb) = @_;
   695 	my($fn,$dta,$fe,$le,$lb) = @_;
   704 	local our($ndt,$buf,$id,$start_ens,@WBRofs);
   711 	local our($ndt,$buf,$id,$start_ens,@WBRofs);
   705 
   712 
   706     sysseek(WBRF,0,0) || die("$WBRcfn: $!");
   713     sysseek(WBRF,0,0) || die("$WBRcfn: $!");
   707 ENSEMBLE:
   714 ENSEMBLE:
   708 	for ($ens=0; 1; $ens++) {
   715 	for ($ens=0; 1; $ens++) {
       
   716 #		die unless defined($global::readDataProgress);
       
   717 		print(STDERR '.') if ($global::readDataProgress>0 && ($ens%$global::readDataProgress)==0);
   709 		$start_ens = goto_next_ens(\*WBRF);
   718 		$start_ens = goto_next_ens(\*WBRF);
   710 		last unless defined($start_ens);
   719 		last unless defined($start_ens);
   711 
   720 
   712 		#----------------------------------------
   721 		#----------------------------------------
   713 		# Handle first_ens and last_ens
   722 		# Handle first_ens and last_ens
   740 		} else {
   749 		} else {
   741 			${$E}[$ens]->{PRODUCER} = 'unknown';
   750 			${$E}[$ens]->{PRODUCER} = 'unknown';
   742 	    }
   751 	    }
   743 
   752 
   744 		if (defined($ens_length) && ($el != $ens_length)) {
   753 		if (defined($ens_length) && ($el != $ens_length)) {
       
   754 			$RDI_PD0_IO::File_Dirty = 1;
   745 			print(STDERR "WARNING (RDI_PD0_IO): ensemble ${$E}[$#{$E}]->{NUMBER} skipped (unexpected length)\n");
   755 			print(STDERR "WARNING (RDI_PD0_IO): ensemble ${$E}[$#{$E}]->{NUMBER} skipped (unexpected length)\n");
   746 			pop(@{$E});
   756 			pop(@{$E});
   747 			$ens--;
   757 			$ens--;
   748 			next;
   758 			next;
   749 		}
   759 		}
   750 		
   760 		
   751 		$ens_length = $el;
   761 		$ens_length = $el;
   752 
   762 
   753 ##		printf(STDERR "$WBRcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last
   763 ##		printf(STDERR "$WBRcfn: WARNING: unexpected number of data types (%d, ens=$ens)\n",$ndt),last
   754 ##				unless ($ndt == 6 || $ndt == 7);
   764 ##				unless ($ndt == 6 || $ndt == 7);
   755 		sysread(WBRF,$buf,2*$ndt) == 2*$ndt || die("$WBRcfn: $!");
   765 		my($nread) = sysread(WBRF,$buf,2*$ndt);						# 2019 EPR test
       
   766 		if ($nread != 2*$ndt) {
       
   767 			printf(STDERR "$WBRcfn: WARNING: expected to read %d bytes, got only %d in ensemble %d\n",
       
   768 							2*$ndt,$nread,${$E}[$ens]->{NUMBER});
       
   769 			last;							
       
   770         }
       
   771 
       
   772 
   756 		@WBRofs = unpack("v$ndt",$buf);
   773 		@WBRofs = unpack("v$ndt",$buf);
   757 		$fixed_leader_bytes = $WBRofs[1] - $WBRofs[0];
   774 		$fixed_leader_bytes = $WBRofs[1] - $WBRofs[0];
   758 #		print(STDERR "@WBRofs\n");
   775 #		print(STDERR "@WBRofs\n");
   759 	
   776 	
   760 		#-------------------------------
   777 		#-------------------------------
   798 
   815 
   799 #		if ($fixed_leader_bytes==42 || $fixed_leader_bytes==58) {				# BB150 & Explorer DVL (if DISABLED!)
   816 #		if ($fixed_leader_bytes==42 || $fixed_leader_bytes==58) {				# BB150 & Explorer DVL (if DISABLED!)
   800 			sysread(WBRF,$buf,7) == 7 || die("$WBRcfn: $!");					# always read pre-Y2K clock
   817 			sysread(WBRF,$buf,7) == 7 || die("$WBRcfn: $!");					# always read pre-Y2K clock
   801 			(${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH},
   818 			(${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH},
   802 			 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},
   819 			 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},
   803 			 ${$E}[$ens]->{SECONDS},$B4) = unpack('CCCCCCC',$buf);
   820 			 ${$E}[$ens]->{SECOND},$B4) = unpack('CCCCCCC',$buf);
   804 			${$E}[$ens]->{SECONDS} += $B4/100;
   821 			${$E}[$ens]->{SECOND} += $B4/100;
   805 			${$E}[$ens]->{YEAR} += (${$E}[$ens]->{YEAR} > 80) ? 1900 : 2000;
   822 			${$E}[$ens]->{YEAR} += (${$E}[$ens]->{YEAR} > 80) ? 1900 : 2000;
   806 #		} else {
   823 #		} else {
   807 #			sysseek(WBRF,7,1) || die("$WBRcfn: $!");							# use Y2K RTC instead
   824 #			sysseek(WBRF,7,1) || die("$WBRcfn: $!");							# use Y2K RTC instead
   808 #		}
   825 #		}
   809 
   826 
   810 		sysread(WBRF,$buf,1) == 1 || die("$WBRcfn: $!");
   827 		sysread(WBRF,$buf,1) == 1 || die("$WBRcfn: $!");
   811 		$ensNo += unpack('C',$buf) << 16;
   828 		$ensNo += unpack('C',$buf) << 16;
   812 
   829 
   813 		for (my($i)=$ens; $i>0; $i--) {											# check for duplicate ens; e.g. 2018 S4P 24UL
   830 		for (my($i)=$ens; $i>0; $i--) {											# check for duplicate ens; e.g. 2018 S4P 24UL
   814 			if (${$E}[$i]->{NUMBER} == $ensNo) {									
   831 			if (${$E}[$i]->{NUMBER} == $ensNo) {									
       
   832 				$RDI_PD0_IO::File_Dirty = 1;
   815 				print(STDERR "WARNING (RDI_PD0_IO): duplicate ensemble $ensNo skipped\n");
   833 				print(STDERR "WARNING (RDI_PD0_IO): duplicate ensemble $ensNo skipped\n");
   816 				pop(@{$E});
   834 				pop(@{$E});
   817 				$ens--;
   835 				$ens--;
   818 				next ENSEMBLE;
   836 				next ENSEMBLE;
   819 			}
   837 			}
   866 			sysread(WBRF,$buf,23) == 23 || die("$WBRcfn: $!");
   884 			sysread(WBRF,$buf,23) == 23 || die("$WBRcfn: $!");
   867 			(${$E}[$ens]->{ERROR_STATUS_WORD},
   885 			(${$E}[$ens]->{ERROR_STATUS_WORD},
   868 		 	 $dummy,${$E}[$ens]->{PRESSURE},${$E}[$ens]->{PRESSURE_STDDEV},
   886 		 	 $dummy,${$E}[$ens]->{PRESSURE},${$E}[$ens]->{PRESSURE_STDDEV},
   869 			 $dummy,${$E}[$ens]->{YEAR},$B3,${$E}[$ens]->{MONTH},
   887 			 $dummy,${$E}[$ens]->{YEAR},$B3,${$E}[$ens]->{MONTH},
   870 			 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},
   888 			 ${$E}[$ens]->{DAY},${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},
   871 			 ${$E}[$ens]->{SECONDS},$B4)
   889 			 ${$E}[$ens]->{SECOND},$B4)
   872 				= unpack('VvVVCCCCCCCCC',$buf);
   890 				= unpack('VvVVCCCCCCCCC',$buf);
   873 
   891 
   874 			${$E}[$ens]->{PRESSURE} /= 1000;
   892 			${$E}[$ens]->{PRESSURE} /= 1000;
   875 			${$E}[$ens]->{PRESSURE_STDDEV} /= 1000;
   893 			${$E}[$ens]->{PRESSURE_STDDEV} /= 1000;
   876 			${$E}[$ens]->{YEAR} *= 100; ${$E}[$ens]->{YEAR} += $B3;
   894 			${$E}[$ens]->{YEAR} *= 100; ${$E}[$ens]->{YEAR} += $B3;
   877 			${$E}[$ens]->{SECONDS} += $B4/100;
   895 			${$E}[$ens]->{SECOND} += $B4/100;
   878 		}
   896 		}
   879 
   897 
   880 # 		THE FOLLOWING LINE OF CODE WAS REMOVED 7/30/2016 WHEN I ADDED A POP
   898 # 		THE FOLLOWING LINE OF CODE WAS REMOVED 7/30/2016 WHEN I ADDED A POP
   881 #		TO THE last STATEMENT ABOVE (INCOMPLETE ENSEMBLE)
   899 #		TO THE last STATEMENT ABOVE (INCOMPLETE ENSEMBLE)
   882 #		THE LINE WAS RE-ENABLED ON 12/23/2017 BECAUSE OTHERWISE THE
   900 #		THE LINE WAS RE-ENABLED ON 12/23/2017 BECAUSE OTHERWISE THE
   897 									 ${$E}[$ens]->{DAY},
   915 									 ${$E}[$ens]->{DAY},
   898 									 ${$E}[$ens]->{YEAR});
   916 									 ${$E}[$ens]->{YEAR});
   899 		${$E}[$ens]->{TIME}
   917 		${$E}[$ens]->{TIME}
   900 			= sprintf("%02d:%02d:%05.02f",${$E}[$ens]->{HOUR},
   918 			= sprintf("%02d:%02d:%05.02f",${$E}[$ens]->{HOUR},
   901 										  ${$E}[$ens]->{MINUTE},
   919 										  ${$E}[$ens]->{MINUTE},
   902 									 	  ${$E}[$ens]->{SECONDS});
   920 									 	  ${$E}[$ens]->{SECOND});
   903 		${$E}[$ens]->{DAYNO}
   921 		${$E}[$ens]->{DAYNO}
   904 			= &_dayNo(${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH},${$E}[$ens]->{DAY},
   922 			= &_dayNo(${$E}[$ens]->{YEAR},${$E}[$ens]->{MONTH},${$E}[$ens]->{DAY},
   905 					  ${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},${$E}[$ens]->{SECONDS});
   923 					  ${$E}[$ens]->{HOUR},${$E}[$ens]->{MINUTE},${$E}[$ens]->{SECOND});
   906 
   924 
   907 		# when analyzing an STA file from an OS75 SADCP (Poseidon),
   925 		# when analyzing an STA file from an OS75 SADCP (Poseidon),
   908 		# I noticed that there is no time information. This causes
   926 		# I noticed that there is no time information. This causes
   909 		# timegm to bomb. 
   927 		# timegm to bomb. 
   910 		if (${$E}[$ens]->{MONTH} == 0) {					# no time info
   928 		if (${$E}[$ens]->{MONTH} == 0) {					# no time info
   916 				= timegm(0,${$E}[$ens]->{MINUTE},
   934 				= timegm(0,${$E}[$ens]->{MINUTE},
   917 						   ${$E}[$ens]->{HOUR},
   935 						   ${$E}[$ens]->{HOUR},
   918 						   ${$E}[$ens]->{DAY},
   936 						   ${$E}[$ens]->{DAY},
   919 						   ${$E}[$ens]->{MONTH}-1,			# timegm jan==0!!!
   937 						   ${$E}[$ens]->{MONTH}-1,			# timegm jan==0!!!
   920 						   ${$E}[$ens]->{YEAR})
   938 						   ${$E}[$ens]->{YEAR})
   921 				  + ${$E}[$ens]->{SECONDS};
   939 				  + ${$E}[$ens]->{SECOND};
   922 	
   940 	
   923 			$dayStart = timegm(0,0,0,${$E}[$ens]->{DAY},
   941 			$dayStart = timegm(0,0,0,${$E}[$ens]->{DAY},
   924 									 ${$E}[$ens]->{MONTH}-1,
   942 									 ${$E}[$ens]->{MONTH}-1,
   925 									 ${$E}[$ens]->{YEAR})
   943 									 ${$E}[$ens]->{YEAR})
   926 				unless defined($dayStart);
   944 				unless defined($dayStart);
  1088 #			sysseek(WBRF,8,1) || die("$WBRcfn: $!");							# remainder of ensemble
  1106 #			sysseek(WBRF,8,1) || die("$WBRcfn: $!");							# remainder of ensemble
  1089         }
  1107         }
  1090         sysseek(WBRF,$start_ens+$ens_length+2,0) || die("$WBRcfn: $!");
  1108         sysseek(WBRF,$start_ens+$ens_length+2,0) || die("$WBRcfn: $!");
  1091 	} # ens loop
  1109 	} # ens loop
  1092 }
  1110 }
       
  1111 print(STDERR "\n") if ($global::readDataProgress > 0);
  1093 
  1112 
  1094 sub WBRdtaIndex($)
  1113 sub WBRdtaIndex($)
  1095 {
  1114 {
  1096 	my($trgid) = @_;
  1115 	my($trgid) = @_;
  1097 	our($ndt,$buf,$id,$start_ens,@WBRofs);
  1116 	our($ndt,$buf,$id,$start_ens,@WBRofs);
  1119 
  1138 
  1120 sub writeData(@)
  1139 sub writeData(@)
  1121 {
  1140 {
  1122 	my($fn,$dta) = @_;
  1141 	my($fn,$dta) = @_;
  1123 
  1142 
  1124 	die("writeData() needs \$WBRcfn from previous readData()")
  1143 	die("writeData() needs \$WBRcfn from previous readData()\n")
  1125 		unless (length($WBRcfn) > 0);
  1144 		unless (length($WBRcfn) > 0);
       
  1145 	die("writeData() only works with clean PD0 files\n")
       
  1146 		if ($RDI_PD0_IO::File_Dirty);
  1126 
  1147 
  1127     sysseek(WBRF,0,0) || die("$WBRcfn: $!");						# rewind input file
  1148     sysseek(WBRF,0,0) || die("$WBRcfn: $!");						# rewind input file
  1128 	$WBPcfn = $fn;													# set patch file name for error messages
  1149 	$WBPcfn = $fn;													# set patch file name for error messages
  1129 	open(WBPF,"+>$WBPcfn") || die("$WBPcfn: $!");					# open patch file for r/w
  1150 	open(WBPF,"+>$WBPcfn") || die("$WBPcfn: $!");					# open patch file for r/w
  1130 
  1151 
  1242 			($dta->{ENSEMBLE}[$ens]->{YEAR},
  1263 			($dta->{ENSEMBLE}[$ens]->{YEAR},
  1243 			 $dta->{ENSEMBLE}[$ens]->{MONTH},
  1264 			 $dta->{ENSEMBLE}[$ens]->{MONTH},
  1244 			 $dta->{ENSEMBLE}[$ens]->{DAY},
  1265 			 $dta->{ENSEMBLE}[$ens]->{DAY},
  1245 			 $dta->{ENSEMBLE}[$ens]->{HOUR},
  1266 			 $dta->{ENSEMBLE}[$ens]->{HOUR},
  1246 			 $dta->{ENSEMBLE}[$ens]->{MINUTE},
  1267 			 $dta->{ENSEMBLE}[$ens]->{MINUTE},
  1247 			 $dta->{ENSEMBLE}[$ens]->{SECONDS},$B4) =
  1268 			 $dta->{ENSEMBLE}[$ens]->{SECOND},$B4) =
  1248 				unpack('CCCCCCC',$buf);
  1269 				unpack('CCCCCCC',$buf);
  1249 			$dta->{ENSEMBLE}[$ens]->{SECONDS} += $B4/100;
  1270 			$dta->{ENSEMBLE}[$ens]->{SECOND} += $B4/100;
  1250 			$dta->{ENSEMBLE}[$ens]->{YEAR} += ($dta->{ENSEMBLE}[$ens]->{YEAR} > 80) ? 1900 : 2000;
  1271 			$dta->{ENSEMBLE}[$ens]->{YEAR} += ($dta->{ENSEMBLE}[$ens]->{YEAR} > 80) ? 1900 : 2000;
  1251 		}
  1272 		}
  1252 		
  1273 		
  1253 		#----------------------------------------------------------------------
  1274 		#----------------------------------------------------------------------
  1254 		# Variable Leader #2
  1275 		# Variable Leader #2
  1297 
  1318 
  1298 		sysseek(WBPF,$start_ens+$WBPofs[1]+57,0) || die("$WBPcfn: $!");			# jump to RTC_CENTURY
  1319 		sysseek(WBPF,$start_ens+$WBPofs[1]+57,0) || die("$WBPcfn: $!");			# jump to RTC_CENTURY
  1299 
  1320 
  1300 		my($century) 	= int($dta->{ENSEMBLE}[$ens]->{YEAR} / 100);
  1321 		my($century) 	= int($dta->{ENSEMBLE}[$ens]->{YEAR} / 100);
  1301 		my($year)	 	=     $dta->{ENSEMBLE}[$ens]->{YEAR} % 100;
  1322 		my($year)	 	=     $dta->{ENSEMBLE}[$ens]->{YEAR} % 100;
  1302 		my($seconds) 	= int($dta->{ENSEMBLE}[$ens]->{SECONDS});
  1323 		my($seconds) 	= int($dta->{ENSEMBLE}[$ens]->{SECOND});
  1303 		my($hundredths) = 100 * ($dta->{ENSEMBLE}[$ens]->{SECONDS} - $seconds);
  1324 		my($hundredths) = 100 * ($dta->{ENSEMBLE}[$ens]->{SECOND} - $seconds);
  1304 		$buf = pack('CCCCCCCC',$century,$year,$dta->{ENSEMBLE}[$ens]->{MONTH},
  1325 		$buf = pack('CCCCCCCC',$century,$year,$dta->{ENSEMBLE}[$ens]->{MONTH},
  1305 							   $dta->{ENSEMBLE}[$ens]->{DAY},$dta->{ENSEMBLE}[$ens]->{HOUR},
  1326 							   $dta->{ENSEMBLE}[$ens]->{DAY},$dta->{ENSEMBLE}[$ens]->{HOUR},
  1306 							   $dta->{ENSEMBLE}[$ens]->{MINUTE},$seconds,$hundredths);
  1327 							   $dta->{ENSEMBLE}[$ens]->{MINUTE},$seconds,$hundredths);
  1307 		my($nw) = syswrite(WBPF,$buf,8);
  1328 		my($nw) = syswrite(WBPF,$buf,8);
  1308 		$nw == 8 || die("$WBPcfn: $nw bytes written ($!)");
  1329 		$nw == 8 || die("$WBPcfn: $nw bytes written ($!)");