.
authorA.M. Thurnherr <athurnherr@yahoo.com>
Sun, 02 Dec 2012 10:55:46 +0000
changeset 11 9e5eba6992f7
parent 10 7e76fdef8953
child 12 2adcd220b9b4
.
LADCP_w
LWplot_TL
LWplot_TLhist
Utilities/README
Utilities/post_merge_TL_check.pl
defaults.pl
time_lag.pl
--- a/LADCP_w	Mon Oct 15 20:28:20 2012 +0000
+++ b/LADCP_w	Sun Dec 02 10:55:46 2012 +0000
@@ -2,9 +2,9 @@
 #======================================================================
 #                    L A D C P _ W 
 #                    doc: Fri Dec 17 18:11:13 2010
-#                    dlm: Mon Oct 15 09:43:38 2012
+#                    dlm: Wed Oct 17 12:03:12 2012
 #                    (c) 2010 A.M. Thurnherr
-#                    uE-Info: 116 10 NIL 0 0 72 2 2 4 NIL ofnI
+#                    uE-Info: 121 63 NIL 0 0 72 2 2 4 NIL ofnI
 #======================================================================
 
 # TODO:
@@ -114,6 +114,11 @@
 #				  - added correctAttitude()
 #	May 22, 2012: - adapted to ANTS V5
 #	Oct 15, 2012: - added $edit_data_hook
+#--- hg commit
+#				  - separated dc/uc time lagging
+#				  - removed support for TLhist
+#	Oct 16, 2012: - added support for dc/uc only solutions
+#	Oct 17, 2012: - renamed $edit_data_hook to $post_merge_hook
 
 # CTD REQUIREMENTS
 #	- elapsed		elapsed seconds; see note below
@@ -141,6 +146,8 @@
 #	  file; this is required in order to be able to compare the times
 #	  from the uplooker and downlooker-derived vertical velocity
 #	  profiles
+#	- the .TL files use the LADCP elapsed time in output; as a result,
+#	  the DL/UL .TL files have different time axes!
 #	- as a result, a profile only starts with elapsed==0 if the CTD
 #	  is turned on when the LADCP is already in the water
 
@@ -229,7 +236,6 @@
 $out_w 	    	= ">$out_w" 		 unless ($out_w =~ /^$|^\s*\|/);	# make sure O_CREAT is set unless it's a pipe
 $out_BR 	    = ">$out_BR" 		 unless ($out_BR =~ /^$|^\s*\|/);
 $out_TL 	    = ">$out_TL" 		 unless ($out_TL =~ /^$|^\s*\|/);
-$out_TLhist    	= ">$out_TLhist" 	 unless ($out_TLhist =~ /^$|^\s*\|/);
 $out_LADCPtis  	= ">$out_LADCPtis"   unless ($out_LADCPtis =~ /^$|^\s*\|/);
 $out_profile    = ">$out_profile" 	 unless ($out_profile =~ /^$|^\s*\|/);
 $out_timeseries = ">$out_timeseries" unless ($out_timeseries =~ /^$|^\s*\|/);
@@ -607,14 +613,28 @@
 if ($opt_u) {
 	progress("\tskipping time lagging (-u)\n");
 } else {
-	$CTD{TIME_LAG} = calc_lag($number_of_timelag_windows[0],$length_of_timelag_windows[0],int(1/$CTD{DT}+0.5));
+	$CTD{TIME_LAG} =													# stage 1: dc/uc combined
+		calc_lag($number_of_timelag_windows[0],$length_of_timelag_windows[0],int(1/$CTD{DT}+0.5),0);
+	croak("$0: Cannot proceed without valid lag!\n") unless defined($CTD{TIME_LAG});
 	progress("\telapsed(CTD) ~ elapsed(LADCP) + %.2fs\n",$CTD{TIME_LAG});
 	
-	$CTD{TIME_LAG} = calc_lag($number_of_timelag_windows[1],$length_of_timelag_windows[1],1);
-	progress("\telapsed(CTD) = elapsed(LADCP) + %.2fs\n",$CTD{TIME_LAG});
+	$CTD{TIME_LAG_DC} = calc_lag($number_of_timelag_windows[1],$length_of_timelag_windows[1],1,1);
+	progress("\tdowncast: elapsed(CTD) = elapsed(LADCP) + %.2fs\n",$CTD{TIME_LAG_DC})
+		if defined($CTD{TIME_LAG_DC});
+	$CTD{TIME_LAG_UC} = calc_lag($number_of_timelag_windows[1],$length_of_timelag_windows[1],1,-1);
+	progress("\tupcast  : elapsed(CTD) = elapsed(LADCP) + %.2fs\n",$CTD{TIME_LAG_UC})
+		if defined($CTD{TIME_LAG_UC});
+
+	croak("$0: Cannot proceed without either down- or upcast time-lag!\n")
+		unless defined($CTD{TIME_LAG_DC}) || defined($CTD{TIME_LAG_UC});
+	$CTD_time_lag_dc = $CTD{TIME_LAG_DC};									# if one lag is missing ...
+	$CTD_time_lag_uc = $CTD{TIME_LAG_UC};									# use other for entire ...
+	$CTD_time_lag_dc = $CTD_time_lag_uc unless defined($CTD_time_lag_dc);	# cast
+	$CTD_time_lag_uc = $CTD_time_lag_dc unless defined($CTD_time_lag_uc);
 }
 
-&antsAddParams('CTD_time_lag',$CTD{TIME_LAG});
+&antsAddParams('CTD_time_lag_dc',$CTD{TIME_LAG_DC},'CTD_time_lag_uc',$CTD{TIME_LAG_UC});
+undef($CTD{TIME_LAG}); 													# to avoid confusion
 
 #------------------------------------------------
 # Merge CTD with LADCP data
@@ -624,7 +644,9 @@
 progress("Merging CTD with LADCP data...\n");
 
 for (my($skipped)=0,my($ens)=$firstGoodEns; $ens<=$lastGoodEns; $ens++) {
-	my($scan) = int(($LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD{TIME_LAG} - $CTD{ELAPSED}[0]) / $CTD{DT} + 0.5);
+	my($scan) = ($ens < $LADCP_atbottom) ?
+		int(($LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD_time_lag_dc - $CTD{ELAPSED}[0]) / $CTD{DT} + 0.5) :
+		int(($LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD_time_lag_uc - $CTD{ELAPSED}[0]) / $CTD{DT} + 0.5);
 	if ($scan <= 0) {	# NB: must be <=, rather than <, or assertion below sometimes fails
 		$skipped++;
 		$firstGoodEns = $ens+1;
@@ -644,13 +666,23 @@
 		last;
 	}
 
-	die("assertion failed!\n" .
-		"\ttest: abs($LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD{TIME_LAG} - $CTD{ELAPSED}[$scan]) <= $CTD{DT}/2\n" .
-		"\tens = $ens, scan = $scan\n" .
-		sprintf("\tadjusted LADCP time = %f\n",$LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD{TIME_LAG}) .
-		sprintf("\tCTD($scan) time = %f\n",$CTD{ELAPSED}[$scan]) .
-		"=> Did you use SeaBird elapsed time? Don't!"
-	) unless (abs($LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD{TIME_LAG} - $CTD{ELAPSED}[$scan]) <= $CTD{DT}/2 + 1e-10);
+	if ($ens < $LADCP_atbottom) {
+		die("assertion failed!\n" .
+			"\ttest: abs($LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD_time_lag_dc - $CTD{ELAPSED}[$scan]) <= $CTD{DT}/2\n" .
+			"\tens = $ens, scan = $scan\n" .
+			sprintf("\tadjusted LADCP time = %f\n",$LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD_time_lag_dc) .
+			sprintf("\tCTD($scan) time = %f\n",$CTD{ELAPSED}[$scan]) .
+			"=> Did you use SeaBird elapsed time? Don't!"
+	    ) unless (abs($LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD_time_lag_dc - $CTD{ELAPSED}[$scan]) <= $CTD{DT}/2 + 1e-10);
+	} else {
+		die("assertion failed!\n" .
+			"\ttest: abs($LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD_time_lag_uc - $CTD{ELAPSED}[$scan]) <= $CTD{DT}/2\n" .
+			"\tens = $ens, scan = $scan\n" .
+			sprintf("\tadjusted LADCP time = %f\n",$LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD_time_lag_uc) .
+			sprintf("\tCTD($scan) time = %f\n",$CTD{ELAPSED}[$scan]) .
+			"=> Did you use SeaBird elapsed time? Don't!"
+	    ) unless (abs($LADCP{ENSEMBLE}[$ens]->{ELAPSED} + $CTD_time_lag_uc - $CTD{ELAPSED}[$scan]) <= $CTD{DT}/2 + 1e-10);
+	}
 
 	$LADCP{ENSEMBLE}[$ens]->{CTD_ELAPSED} = $CTD{ELAPSED}[$scan];		# elapsed field for output
 
@@ -764,9 +796,9 @@
 $nerm = editSurfLayer($firstGoodEns,$lastGoodEns,$surface_layer_depth);
 progress("\t$nerm ensembles removed\n");
 
-if (defined($edit_data_hook)) {
-	progress("Executing user-supplied \$edit_data_hook...\n");
-	&{$edit_data_hook}($firstGoodEns,$lastGoodEns);
+if (defined($post_merge_hook)) {
+	progress("Executing user-supplied \$post_merge_hook...\n");
+	&{$post_merge_hook}($firstGoodEns,$lastGoodEns);
 }
 
 #---------------------------------------------------------------------------
@@ -837,7 +869,6 @@
 	$DNCAST{N_SAMP}[$bi]		= @{$DNCAST{W}[$bi]};
 }
 
-
 progress("\tupcast...\n");														# upcast
 
 my($realLastGoodEns);
@@ -904,7 +935,10 @@
 unless ($opt_q) {
 	progress("Removing single-ping residual noise...\n");
 	
-	for ($ens=$firstGoodEns; $ens<=$realLastGoodEns; $ens++) {
+	my($fe) = defined($CTD{TIME_LAG_DC}) ? $firstGoodEns    : $LADCP_atbottom;
+	my($le) = defined($CTD{TIME_LAG_UC}) ? $realLastGoodEns : $LADCP_atbottom;
+
+	for ($ens=$fe; $ens<=$le; $ens++) {
 		next unless numberp($LADCP{ENSEMBLE}[$ens]->{CTD_DEPTH});
 		my(@residuals) = ();
 		my(@bindepth) = calc_binDepths($ens);
@@ -1023,7 +1057,9 @@
 					  'pitch','roll','tilt','heading','3_beam','svel');
 
 	open(STDOUT,"$out_w") || croak("$out_w: $!\n");
-	for ($ens=$firstGoodEns; $ens<$LADCP_atbottom; $ens++) {						# downcast
+
+	if (defined($CTD{TIME_LAG_DC})) {
+	  for ($ens=$firstGoodEns; $ens<$LADCP_atbottom; $ens++) {						# downcast
 		next unless numberp($LADCP{ENSEMBLE}[$ens]->{CTD_DEPTH});
 		my(@bindepth) = calc_binDepths($ens);
 		for ($bin=$LADCP_firstBin-1; $bin<=$LADCP_lastBin-1; $bin++) {
@@ -1053,10 +1089,12 @@
 				 defined($LADCP{ENSEMBLE}[$ens]->{VELOCITY}[$bin][3])) < 4 ? 1 : 0,
 				$CTD{SVEL}[$LADCP{ENSEMBLE}[$ens]->{CTD_SCAN}],
 			);
-		}
-	}
+		} # for $bin
+	  } # for $ens
+	} # if defined dc time lag
 	
-	for ($ens=$LADCP_atbottom; $ens<=$realLastGoodEns; $ens++) {						# upcast 
+	if (defined($CTD{TIME_LAG_UC})) {
+	  for ($ens=$LADCP_atbottom; $ens<=$realLastGoodEns; $ens++) {						# upcast 
 		next unless numberp($LADCP{ENSEMBLE}[$ens]->{CTD_DEPTH});
 		my(@bindepth) = calc_binDepths($ens);
 		for ($bin=$LADCP_firstBin-1; $bin<=$LADCP_lastBin-1; $bin++) {
@@ -1086,8 +1124,9 @@
 				 defined($LADCP{ENSEMBLE}[$ens]->{VELOCITY}[$bin][3])) < 4 ? 1 : 0,
 				$CTD{SVEL}[$LADCP{ENSEMBLE}[$ens]->{CTD_SCAN}],
 			);
-		}
-	}
+		} # for $bin
+	  } # for $ens
+	} # if defined uc time-lag
 
 	&antsOut('EOF'); open(STDOUT,">&2");
 }
@@ -1106,6 +1145,8 @@
 
 	open(STDOUT,"$out_profile") || croak("$out_profile: $!\n");
 
+	undef(%DNCAST) unless defined($CTD{TIME_LAG_DC});
+	undef(%UPCAST) unless defined($CTD{TIME_LAG_UC});
 	for (my($bi)=0; $bi<=max($#{$DNCAST{ENSEMBLE}},$#{$UPCAST{ENSEMBLE}},$#{$BT{NSAMP}}); $bi++) {
 		&antsOut(($bi+0.5)*$output_bin_size,					# nominal depth
 				 $DNCAST{MEAN_DEPTH}[$bi],$DNCAST{MEAN_ELAPSED}[$bi],
--- a/LWplot_TL	Mon Oct 15 20:28:20 2012 +0000
+++ b/LWplot_TL	Sun Dec 02 10:55:46 2012 +0000
@@ -2,9 +2,9 @@
 #======================================================================
 #                    L W P L O T _ T L 
 #                    doc: Thu Oct 13 10:51:49 2011
-#                    dlm: Wed Apr 18 10:33:35 2012
+#                    dlm: Tue Oct 16 13:02:45 2012
 #                    (c) 2011 A.M. Thurnherr
-#                    uE-Info: 18 0 NIL 0 0 72 0 2 4 NIL ofnI
+#                    uE-Info: 20 52 NIL 0 0 72 0 2 4 NIL ofnI
 #======================================================================
 
 # HISTORY:
@@ -15,6 +15,9 @@
 #	Nov 14, 2011: - added file layout check
 #	Mar 12, 2012: - sh -> ksh as this does not work with /bin/sh on MacOSX 10.6.4
 #   Apr 12, 2012: - made re-entrant
+#	Oct 12, 2012: - split dc/uc time lagging
+#				  - reduced number of xtic labels 
+#	Oct 16, 2012: - renamed elapsed to elapsed.LADCP
 
 USAGE="Usage: $0 <eps-file> [in-file]"
 	[ $# -eq 2 ] && exec <"$2" "$0" "$1"
@@ -29,12 +32,14 @@
 	[ -z "$run_label" ] && run_label=`expr -- "$line" : '#ANTS#PARAMS#.*run_label{\([^}]*\)}`
 	[ -z "$min_elapsed" ] && min_elapsed=`expr -- "$line" : '#ANTS#PARAMS#.*elapsed.min{\([^}]*\)}`
 	[ -z "$max_elapsed" ] && max_elapsed=`expr -- "$line" : '#ANTS#PARAMS#.*elapsed.max{\([^}]*\)}`
-	[ -z "$best_scan_offset" ] && best_scan_offset=`expr -- "$line" : '#ANTS#PARAMS#.*best_scan_offset{\([^}]*\)}`
+	[ -z "$bot_elapsed" ] && bot_elapsed=`expr -- "$line" : '#ANTS#PARAMS#.*elapsed.bot{\([^}]*\)}`
+	[ -z "$best_scan_offset_dc" ] && best_scan_offset_dc=`expr -- "$line" : '#ANTS#PARAMS#.*best_scan_offset\.dc{\([^}]*\)}`
+	[ -z "$best_scan_offset_uc" ] && best_scan_offset_uc=`expr -- "$line" : '#ANTS#PARAMS#.*best_scan_offset\.uc{\([^}]*\)}`
 	[ -z "$fields" ] && fields=`expr -- "$line" : '#ANTS#FIELDS# \(.*\)' | sed -e s/{//g -e s/}//g`
 done
 
 set -- $fields
-[ "$1" = elapsed -a "$2" = scan_offset -a "$4" = downcast ] || {
+[ "$1" = elapsed.LADCP -a "$2" = scan_offset -a "$4" = downcast ] || {
 	echo "$0: file layout error ($1,$2,$4)" >&2
 	exit 1
 }
@@ -63,7 +68,7 @@
 
 awk '{if ($4 == 1) { print $1/60,$2; }}' $TMPFILE \
 	| psxy -P -K $J $R \
-		   -Bf1a15:"Elapsed Time [min]":/f1a5:"Best Offset [scans]":WeSn \
+		   -Bf1a30:"Elapsed Time [min]":/f1a5:"Best Offset [scans]":WeSn \
 		   -Sc0.1 -Gcoral \
 	> "$eps_file"		   
 	
@@ -73,8 +78,10 @@
 	
 echo 0.02 0.98 12 0 0 TL $out_basename $run_label | pstext -O -K $U $J >> "$eps_file"
 
-echo -e "`echo $min_elapsed/60|bc` $best_scan_offset\n`echo $max_elapsed/60+1|bc` $best_scan_offset" \
-	| psxy -O $R $J >> "$eps_file"
+echo -e "`echo $min_elapsed/60|bc` $best_scan_offset_dc\n`echo $bot_elapsed/60+1|bc` $best_scan_offset_dc" \
+	| psxy -O -K $R $J -W4/coral >> "$eps_file"
+echo -e "`echo $bot_elapsed/60|bc` $best_scan_offset_uc\n`echo $max_elapsed/60+1|bc` $best_scan_offset_uc" \
+	| psxy -O $R $J -W4/SeaGreen >> "$eps_file"
 
 rm $TMPFILE
 fixbb "$eps_file"
--- a/LWplot_TLhist	Mon Oct 15 20:28:20 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-#!/bin/ksh
-#======================================================================
-#                    L W P L O T _ T L H I S T 
-#                    doc: Thu Oct 13 10:51:49 2011
-#                    dlm: Wed Apr 18 10:34:10 2012
-#                    (c) 2011 A.M. Thurnherr
-#                    uE-Info: 17 0 NIL 0 0 72 2 2 4 NIL ofnI
-#======================================================================
-
-# HISTORY:
-#	Oct 13, 2011: - created
-#	Oct 17, 2011: - turned into filter
-#				  - added %run_label
-#   Nov 14, 2011: - added file layout check
-#	Mar 12, 2012: - sh -> ksh as this does not work with /bin/sh on MacOSX 10.6.4
-#   Apr 12, 2012: - made re-entrant
-
-USAGE="Usage: $0 <eps-file> [in-file]"
-	[ $# -eq 2 ] && exec <"$2" "$0" "$1"
-	[ $# -ne 1 ] && { echo $USAGE >&2; exit 1; }
-eps_file="$1"
-
-while [ -z "$fields" ]
-do
-	read line
-    [ ! -t 1 ] && echo "$line"
-	[ -z "$out_basename" ] && out_basename=`expr -- "$line" : '#ANTS#PARAMS#.*out_basename{\([^}]*\)}`
-	[ -z "$run_label" ] && run_label=`expr -- "$line" : '#ANTS#PARAMS#.*run_label{\([^}]*\)}`
-	[ -z "$n_windows" ] && n_windows=`expr -- "$line" : '#ANTS#PARAMS#.*n_windows{\([^}]*\)}`
-	[ -z "$best_scan_offset" ] && best_scan_offset=`expr -- "$line" : '#ANTS#PARAMS#.*best_scan_offset{\([^}]*\)}`
-	[ -z "$fields" ] && fields=`expr -- "$line" : '#ANTS#FIELDS# \(.*\)' | sed -e s/{//g -e s/}//g`
-done
-
-set -- $fields
-[ "$1" = scan_offset -a "$2" = nsamp ] || {
-	echo "$0: file layout error" >&2
-	exit 1
-}
-
-eps_file="$PWD/$eps_file"	# make outfile name absolute (hopefully, it is not already...)
-mkdir /tmp/$$				# GMT makes tmpfiles and is not reentrant
-cd /tmp/$$
-
-TMPFILE=/tmp/$$.LWplot_TLhist
-if [ ! -t 1 ]
-then
-	tee $TMPFILE
-else
-	cat > $TMPFILE
-fi
-
-[ -f .gmtdefaults4 ] ||
-	gmtset	PAPER_MEDIA letter+ \
-			LABEL_FONT_SIZE 14 ANNOT_FONT_SIZE_PRIMARY 14 \
-			WANT_EURO_FONT true \
-	        PLOT_DEGREE_FORMAT ddd:mm:ssF
-
-R=-R-24/24/0/60
-U=-R0/1/0/1
-J=-JX10
-
-awk "{print \$1, 100*\$2/$n_windows}" $TMPFILE \
-	| psxy -P -K $J $R \
-			-Bf1a10:"Best Offset [scans]":/f1a5:"Fraction [%]":WeSn \
-		    -Sb1u -G127 > "$eps_file"
-	
-echo 0.02 0.98 12 0 0 TL $out_basename $run_label | pstext -O -K $J $U >> "$eps_file"
-
-echo -e "$best_scan_offset 0\n$best_scan_offset 60" \
-	| psxy -O $J $R >> "$eps_file"
-
-rm $TMPFILE
-fixbb "$eps_file"
-
-cd "$PWD"
-rm -rf /tmp/$$
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/README	Sun Dec 02 10:55:46 2012 +0000
@@ -0,0 +1,13 @@
+======================================================================
+                    R E A D M E 
+                    doc: Wed Oct 17 11:57:40 2012
+                    dlm: Wed Oct 17 11:57:40 2012
+                    (c) 2012 A.M. Thurnherr
+                    uE-Info: 5 38 NIL 0 0 72 0 2 4 NIL ofnI
+======================================================================
+
+In oder to use the utilities in this directory, include something like this:
+
+	require "$WCALC/Utilities/post_merge_TL_check.pl";
+
+in the relevant ProcessingParams file.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/post_merge_TL_check.pl	Sun Dec 02 10:55:46 2012 +0000
@@ -0,0 +1,63 @@
+#======================================================================
+#                    U T I L I T I E S / P O S T _ M E R G E _ T L _ C H E C K . P L 
+#                    doc: Wed Oct 12 10:23:58 2011
+#                    dlm: Wed Oct 17 12:06:02 2012
+#                    (c) 2011 A.M. Thurnherr
+#                    uE-Info: 33 15 NIL 0 0 72 2 2 4 NIL ofnI
+#======================================================================
+
+# HISTORY:
+#	Oct 12, 2012: - created as an experimental time-lagging filter
+#	Oct 17, 2012: - turned into this utility
+
+#----------------------------------------------------------------------
+# This code is used to verify (or improve) time lagging
+#	- for each ensemble, a "narrow-band" time lagging is performed
+#	  to determine the optimal scan offset
+#	- time-lag window is taken from 2nd value of -w
+#	- max search radius is hard-coded in $scan_offset_search_window
+#----------------------------------------------------------------------
+
+$post_merge_hook = sub {							# arguments: firstGoodEns, lastGoodEns
+	my($fe,$le) = @_;
+
+	progress("Writing optimal lags for all ensembles to $data_subdir/$out_basename.TLcheck...\n");
+
+	my($scan_offset_search_window) = 10;
+	my($ew_hwidth) =								# window half-width in ensembles
+		int($length_of_timelag_windows[1]/2 / $LADCP{MEAN_DT} + 0.5);
+
+	my(@mad,$nsamp);
+
+	@antsNewLayout = ('ensemble','best_scan_offset','mad');
+	open(STDOUT,">$data_subdir/$out_basename.TLcheck")
+		|| croak("$data_subdir/$out_basename.TLcheck: $!\n");
+
+	for (my($e)=$fe; $e<=$le; $e++) {
+		next unless numberp($LADCP{ENSEMBLE}[$e]->{CTD_DEPTH});						# skip non-valid
+		
+		for (my($so)=-$scan_offset_search_window; $so<=$scan_offset_search_window; $so++) {			# find narrowband best lag
+			$mad[$so + $scan_offset_search_window] = $nsamp = 0;
+			for (my($i)=max($fe,$e-$ew_hwidth); $i<=min($le,$e+$ew_hwidth); $i++) {	# calc mad in window
+				next unless numberp($LADCP{ENSEMBLE}[$i]->{CTD_DEPTH});
+				$mad[$so + $scan_offset_search_window] +=
+					abs($LADCP{ENSEMBLE}[$i]->{REFLR_W} - $CTD{W}[$LADCP{ENSEMBLE}[$i]->{CTD_SCAN}+$so]);
+				$nsamp++;					
+			} # for $i
+			if ($nsamp > 0) {
+				$mad[$so + $scan_offset_search_window] /= $nsamp;
+			} else {
+				$mad[$so + $scan_offset_search_window] = 9e99;
+			}
+		} # for $so
+
+		my($best_so) = min_i(@mad) - $scan_offset_search_window;		
+		&antsOut($e,$best_so,$mad[$best_so + $scan_offset_search_window]);
+
+	}
+
+	&antsOut('EOF'); open(STDOUT,'>&2');
+
+};
+
+1;
--- a/defaults.pl	Mon Oct 15 20:28:20 2012 +0000
+++ b/defaults.pl	Sun Dec 02 10:55:46 2012 +0000
@@ -1,9 +1,9 @@
 #======================================================================
 #                    D E F A U L T S . P L 
 #                    doc: Tue Oct 11 17:11:21 2011
-#                    dlm: Thu Oct 11 14:18:12 2012
+#                    dlm: Mon Oct 15 21:34:00 2012
 #                    (c) 2011 A.M. Thurnherr
-#                    uE-Info: 25 48 NIL 0 0 72 0 2 4 NIL ofnI
+#                    uE-Info: 26 14 NIL 0 0 72 0 2 4 NIL ofnI
 #======================================================================
 
 # HISTORY:
@@ -23,6 +23,8 @@
 #	Oct 27, 2011: - modified ProcessingParam file loading
 #				  - added ${pitch,roll,heading}_bias
 #	Oct 11, 2012: - added .TL output to defaults
+#--- hg commit
+#	Oct 15, 2012: - removed support for TLhist
 
 # Variable Names:
 #	- variables that are only used in a particular library are
--- a/time_lag.pl	Mon Oct 15 20:28:20 2012 +0000
+++ b/time_lag.pl	Sun Dec 02 10:55:46 2012 +0000
@@ -1,9 +1,9 @@
 #======================================================================
 #                    T I M E _ L A G . P L 
 #                    doc: Fri Dec 17 21:59:07 2010
-#                    dlm: Mon Nov 14 15:19:12 2011
+#                    dlm: Tue Oct 16 20:13:38 2012
 #                    (c) 2010 A.M. Thurnherr
-#                    uE-Info: 258 0 NIL 0 0 72 2 2 4 NIL ofnI
+#                    uE-Info: 288 0 NIL 0 0 72 2 2 4 NIL ofnI
 #======================================================================
 
 # HISTORY:
@@ -43,6 +43,10 @@
 #				  - added step to remove all lags with mad > median(mads)
 #	Oct 20, 2011: - losened too-restrictive last step
 #	Oct 21, 2011: - BUG: forgot to update $n_valid_windows while removing outlier lags
+#	Oct 15, 2012: - added $cast_type to &calc_lag()
+#				  - removed support for TLhist
+#	Oct 16, 2012: - renamed field elapsed to elapsed.LADCP for clarity
+#				  - made failure "soft"
 
 # DIFFICULT STATIONS:
 #	NBP0901#131		this requires the search-radius doubling heuristic
@@ -108,17 +112,25 @@
 
 #----------------------------------------------------------------------
 # carry out lag correlations and keep tally of the results
-#	- fist and last 10% of LADCP profile ignored
 #----------------------------------------------------------------------
 
-sub calc_lag($$$)
+{ # STATIC SCOPE
+
+my(@dc_elapsed,@dc_so,@dc_mad);								# buffer 
+
+sub calc_lag($$$$)
 {
-	my($n_windows,$w_size,$scan_increment) = @_;
+	my($n_windows,$w_size,$scan_increment,$cast_type) = @_;
 	my($search_radius) = $scan_increment==1 ? 3 : $w_size;
 
+	my($ctmsg);
+	if ($cast_type == 0) 	{ $ctmsg = "full-cast"; }
+	elsif ($cast_type == 1) { $ctmsg = "down-cast"; }
+	else 					{ $ctmsg = "up-cast"; }
+
 RETRY:
 	my($failed) = undef;
-	progress("Calculating $n_windows time lags from ${w_size}s-long windows at %dHz resolution...\n",
+	progress("Calculating $n_windows $ctmsg time lags from ${w_size}s-long windows at %dHz resolution...\n",
 		int(1/$scan_increment/$CTD{DT}+0.5));
 
 	my($approx_CTD_profile_start_ens) =
@@ -136,9 +148,22 @@
 	my(@elapsed,@so,@mad,%nBest,%madBest);
 	my($n_valid_windows) = 0;
 
+	my($first_ens,$last_ens);
+	if ($cast_type == 0) {													# dc/uc
+		$first_ens = $approx_joint_profile_start_ens;
+		$last_ens  = $approx_joint_profile_end_ens;
+	} elsif ($cast_type == 1) {												# dc
+		$first_ens = $approx_joint_profile_start_ens;
+		$last_ens  = $LADCP_atbottom;
+	} elsif ($cast_type == -1) {											# uc
+		$first_ens = $LADCP_atbottom;
+		$last_ens  = $approx_joint_profile_end_ens;
+	} else {
+		croak("$0: illegal \$cast_type");
+	}
+
 	for (my($wi)=0; $wi<$n_windows; $wi++) {
-		my($fe) = $approx_joint_profile_start_ens + 
-					int(($approx_joint_profile_end_ens-$approx_joint_profile_start_ens-$window_ens)*$wi/($n_windows-1)+0.5);
+		my($fe) = $first_ens + int(($last_ens-$first_ens-$window_ens)*$wi/($n_windows-1)+0.5);
 		my($so,$mad) = bestLag($fe,$fe+$window_ens,$search_radius,$scan_increment);
 		$elapsed[$wi] = $LADCP{ENSEMBLE}[$fe+int($w_size/2/$LADCP{MEAN_DT}+0.5)]->{ELAPSED};
 		die("assertion failed\nfe=$fe, lastGoodEns=$lastGoodEns, w_size=$w_size") unless ($elapsed[$wi]);
@@ -187,8 +212,9 @@
 
 	unless ($nBest{$best_lag[0]}+$nBest{$best_lag[1]}+$nBest{$best_lag[2]} >= $TL_required_top_three_fraction*$n_valid_windows) {
 		if (max(@best_lag)-min(@best_lag) > $TL_max_allowed_three_lag_spread) {
-			$failed = sprintf("$0: cannot determine a valid lag; top 3 tags account for %d%% of total (use -3 to relax criterion)\n",
+			warning(2,"$0: cannot determine a valid $ctmsg lag; top 3 tags account for %d%% of total (use -3 to relax criterion)\n",
 				int(100*($nBest{$best_lag[0]}+$nBest{$best_lag[1]}+$nBest{$best_lag[2]})/$n_valid_windows+0.5));
+			$failed = 1;				
 		} else {
 			warning(1,"top 3 tags account for only %d%% of total\n",
 				int(100*($nBest{$best_lag[0]}+$nBest{$best_lag[1]}+$nBest{$best_lag[2]})/$n_valid_windows+0.5));
@@ -196,19 +222,8 @@
 	}
 
 	my($bmo) = $best_lag[0];
-#	if (max(@best_lag)-min(@best_lag) > 3 || $nBest{$best_lag[0]}/$n_valid_windows >= 2/3) {
-#		progress("\tunambiguously best offset = %d scans\n",$bmo);
-#	} else {
-#		$bmo = ($nBest{$best_lag[0]}*$best_lag[0] +
-#				$nBest{$best_lag[1]}*$best_lag[1] +
-#				$nBest{$best_lag[2]}*$best_lag[2]) / ($nBest{$best_lag[0]} +
-#													  $nBest{$best_lag[1]} +
-#													  $nBest{$best_lag[2]});
-#		progress("\tweighted-mean offset = %.1f scans\n",$bmo);
-#	}
 
 	if ($bmo > 0.9*$search_radius/2/$CTD{DT}) {
-#		$failed = sprintf("$0: cannot determine valid lag (too close to edge of search)\n");
 		if ($search_radius == $w_size) {
 			warning(0,"lag too close to edge of search --- trying again after shifting the initial offset\n");
 			$CTD{TIME_LAG} += $search_radius/2;
@@ -221,7 +236,6 @@
 		goto RETRY;
 	}
 	if (-$bmo > 0.9*$search_radius/2/$CTD{DT}) {
-#		$failed = sprintf("$0: cannot determine valid lag (too close to edge of search)\n");
 		if ($search_radius == $w_size) {
 			warning(0,"lag too close to edge of search --- trying again after shifting the initial offset\n");
 			$CTD{TIME_LAG} -= $search_radius/2;
@@ -237,43 +251,44 @@
 	if (defined($out_TL) && $scan_increment==1) {
 		progress("\tsaving/plotting time-lagging time series...\n");
 	
-		my($saveParams) = $antsCurParams;
-		@antsNewLayout = ('elapsed','scan_offset','mad','downcast');
-		open(STDOUT,"$out_TL") || croak("$out_TL: $!\n");
-
-		&antsAddParams('best_scan_offset',$bmo);
-		&antsAddParams('elapsed.min',$elapsed[0]);
-		&antsAddParams('elapsed.max',$elapsed[$#elapsed]);
-
-		for (my($wi)=0; $wi<@elapsed; $wi++) {
-			&antsOut($elapsed[$wi],$so[$wi],$mad[$wi],$elapsed[$wi]<$LADCP{ENSEMBLE}[$LADCP_atbottom]->{ELAPSED});
-		}
-
-		&antsOut('EOF'); open(STDOUT,">&2");
-		$antsCurParams = $saveParams;
-	}
+		if ($cast_type == 1) {				# dc => buffer data in static scope. output will be produced during uc
+			@dc_elapsed = @elapsed; @dc_so = @so; @dc_mad = @mad;
+			$dc_elapsed_min = $elapsed[0]; $dc_bmo = $bmo;
+		} else {							# uc or duc
+			my($saveParams) = $antsCurParams;
+			@antsNewLayout = ('elapsed.LADCP','scan_offset','mad','downcast');
+			open(STDOUT,"$out_TL") || croak("$out_TL: $!\n");
 	
-	if (defined($out_TLhist) && $scan_increment==1) {
-		progress("\tsaving/plotting time-lagging histogram...\n");
-	
-		my($saveParams) = $antsCurParams;
-		@antsNewLayout = ('scan_offset','nsamp','mad.avg');
-		open(STDOUT,"$out_TLhist") || croak("$out_TLhist: $!\n");
+			if ($cast_type == -1) {			# uc => first output buffered dc data
+				&antsAddParams('best_scan_offset.dc',$dc_bmo);
+				&antsAddParams('best_scan_offset.uc',$bmo);
+				&antsAddParams('elapsed.min',$dc_elapsed_min);
+				&antsAddParams('elapsed.max',$elapsed[$#elapsed]);
+				&antsAddParams('elapsed.bot',$elapsed[0]);
+				for (my($wi)=0; $wi<@dc_elapsed; $wi++) {
+					&antsOut($dc_elapsed[$wi],$dc_so[$wi],$dc_mad[$wi],1);
+				}
+				for (my($wi)=0; $wi<@elapsed; $wi++) {
+					&antsOut($elapsed[$wi],$so[$wi],$mad[$wi],0);
+				}
+			} else {						# duc (not used as of 10/15/2012, but should work with adaptation of [LWplot_TL]
+				&antsAddParams('best_scan_offset',$bmo);
+				&antsAddParams('elapsed.min',$elapsed[0]);
+				&antsAddParams('elapsed.max',$elapsed[$#elapsed]);
+				for (my($wi)=0; $wi<@elapsed; $wi++) {
+					&antsOut($elapsed[$wi],$so[$wi],$mad[$wi],$elapsed[$wi]<$LADCP{ENSEMBLE}[$LADCP_atbottom]->{ELAPSED});
+				}
+			}
 	
-		&antsAddParams('n_windows',$n_windows);
-		&antsAddParams('best_scan_offset',$bmo);
-	
-		for (my($so)=-24; $so<=24; $so++) {
-			&antsOut($so,$nBest{$so}?$nBest{$so}:0,$madBest{$so});
+			&antsOut('EOF'); open(STDOUT,">&2");
+	        $antsCurParams = $saveParams;
 		}
-	
-		&antsOut('EOF'); open(STDOUT,">&2");
-		$antsCurParams = $saveParams;
 	}
 
-	croak($failed) if defined($failed);
-	return $CTD{TIME_LAG}+$bmo*$CTD{DT};
+	return defined($failed) ? undef : $CTD{TIME_LAG}+$bmo*$CTD{DT};
 }
 
+} # STATIC SCOPE
+
 
 1;