LADCP_w_regrid
author A.M. Thurnherr <athurnherr@yahoo.com>
Thu, 30 Jul 2015 09:11:43 +0000
changeset 30 7fb67e771d85
parent 29 c1ff35103176
permissions -rwxr-xr-x
LWplots expunged

#!/usr/bin/perl
#======================================================================
#                    L A D C P _ W _ R E G R I D 
#                    doc: Fri Apr 24 17:15:59 2015
#                    dlm: Mon Jul 27 17:20:23 2015
#                    (c) 2015 A.M. Thurnherr
#                    uE-Info: 182 21 NIL 0 0 72 2 2 4 NIL ofnI
#======================================================================

$antsSummary = 'edit and re-grid LADCP vertical-velocity samples';
$antsMinLibVersion = 6.1;

# HISTORY:
#	Apr 24, 2015: - created
#	Apr 25, 2015: - maded gridding work
#	Apr 26, 2015: - made editing work
#	Apr 27, 2015: - added -p
#	May  5, 2015: - modified Editfile syntax to use parens()
#	May  7, 2015: - allow leading whitespace before Editfile labels
#	May 17, 2015: - removed warning about missing ./Editfile
#	May 18, 2015: - added important %PARAMs for dual-head data
#				  - updated to libV6.1
#	May 19, 2015: - added hab to output
#				  - allow setting %PARAMS in Editfile
#	May 20, 2015: - Editfile => EditParams
#	Jun 18, 2015: - added -i
#				  - implemented default output on -t stdout
#				  - changed to libGMT.pl
#				  - removed dead -d option
#	Jul 26, 2015: - adapted for %outgrid_*
#	Jul 27, 2015: - B-t)rack <wprof>

($ANTS) = (`which ANTSlib` =~ m{^(.*)/[^/]*$});

die("$0: ANTSlib required but not found (bad \$PATH?)\n")
	unless ($ANTS ne '');

require "$ANTS/ants.pl";
require "$ANTS/libstats.pl";
require "$ANTS/libGMT.pl";

&antsUsage('b:i:k:o:p:t:',1,
	'[profile -i)d <id>]',
	'[-o)utput bin <resolution[10m]>] [-k) require <min> samples]',
#	'[valid LADCP -b)ins <bin[2],bin[*][,bin[2],bin[*]]>',
	'[-p)lot <[%03d_wprof.eps]> [B-t)rack <wprof>]]',
	'<.samp file> [.samp file]');

$dual_head = (@ARGV==1);

$opt_o_override = defined($opt_o);
$opt_o = $P{outgrid_dz};
&antsCardOpt(\$opt_o,10);
	
$opt_k_override = defined($opt_k);
$opt_k = 2 * $P{ouput_grid_minsamp}
	if defined($P{ouput_grid_minsamp});
&antsCardOpt(\$opt_k,$dual_head?40:20);

if (defined($opt_b)) {
	croak("$0: -b not implemented yet\n");
	($LADCP_firstBin,$LADCP_lastBin) = split(',',$opt_b);
	croak("$0: cannot decode -b $opt_b\n")
		unless (numberp($LADCP_firstBin) &&
				($LADCP_lastBin eq '*' || numberp($LADCP_lastBin)));
}

#----------------------------------------------------------------------
# Redirect STDOUT to %.wprof & create %_wprof.ps if STDOUT is a tty
#----------------------------------------------------------------------

$id = defined($opt_i) ? $opt_i : &antsParam('profile_id');
croak("$0: no profile_id in first file => -i required\n")
	unless defined($id);
	
if (-t STDOUT) {
	$opt_p = '%03d_wprof.ps' unless defined($opt_p);
	$outfile = sprintf('%03d.wprof',$id);
	open(STDOUT,">$outfile") || die("$outfile: $!\n");
}

croak("$0: -t only makes sense when a plot is produced\n")
	if $opt_t && !defined($opt_p);

#----------------------------------------------------------------------
# Library
#----------------------------------------------------------------------

my(@dscMin,@dscMax,@dscDUc);

sub discard($$$)										# define bad-data filter
{
	my($fnm,$min,$max) = @_;
	my($fnr) = fnr($fnm);
	$dscMin[$fnr] = numberp($min) ? $min : -9e99;
	$dscMax[$fnr] = numberp($max) ? $max :  9e99;
	$dscDUc[$fnr] = 2;
}

sub discard_dc($$$)										# define bad-data filter
{
	my($fnm,$min,$max) = @_;
	my($fnr) = fnr($fnm);
	$dscMin[$fnr] = numberp($min) ? $min : -9e99;
	$dscMax[$fnr] = numberp($max) ? $max :  9e99;
	$dscDUc[$fnr] = 1;
}

sub discard_uc($$$)										# define bad-data filter
{
	my($fnm,$min,$max) = @_;
	my($fnr) = fnr($fnm);
	$dscMin[$fnr] = numberp($min) ? $min : -9e99;
	$dscMax[$fnr] = numberp($max) ? $max :  9e99;
	$dscDUc[$fnr] = 0;
}

sub isBad()
{
	for (my($f)=0; $f<$antsBufNFields; $f++) {
		next unless defined($dscDUc[$f]);
		next unless ($dscDUc[$f]==2 || $dscDUc[$f]==$ants_[0][$dcF]);
		return 1 unless ($ants_[0][$f] < $dscMin[$f]) ||
				        ($ants_[0][$f] > $dscMax[$f]);
	}
	return 0;
}

#----------------------------------------------------------------------
# Edit Data
#----------------------------------------------------------------------

$wF = &fnr('w');
$eF = &fnr('elapsed');
$dF = &fnr('depth');
$bF = &fnr('bin');
$dcF = &fnr('downcast');

$first_label 	= &antsRequireParam('run_label');
$bin_length 	= &antsRequireParam('ADCP_bin_length');
$pulse_length   = &antsRequireParam('ADCP_pulse_length');
$blanking_dist  = &antsRequireParam('ADCP_blanking_distance');
($dayNoP,$dn) = &antsFindParam('dn\d\d');
croak("$0: cannot determine day number\n")
	unless defined($dayNoP);

my($R,$R2);
if ($opt_p) {												# begin plot
	$xmin = -0.1; $x2min = -200;
	$xmax = 0.35; $x2max =	200;
	$ymin =  0;
	$ymax = antsParam('water_depth');
	$ymax = antsRequireParam('max_depth') unless defined($ymax);
	$plotsize = 13;
	$R	= "-R$xmin/$xmax/$ymin/$ymax";
	$R2 = "-R$x2min/$x2max/$ymin/$ymax";
	GMT_begin(sprintf($opt_p,$id),"-JX$plotsize/-$plotsize",$R,'-X6 -Y4');
	GMT_psxy('-W1');
	print(GMT "0 $ymin\n0 $ymax");
	GMT_psxy('-L -G200');
	print(GMT "0.07 $ymin\n0.07 $ymax\n0.18 $ymax\n0.18 $ymin\n");
	GMT_setR($R2);
	GMT_psxy('-M -W1');
	print(GMT ">\n50 $ymin\n50 $ymax\n");
	print(GMT ">\n100 $ymin\n100 $ymax\n");
	print(GMT ">\n150 $ymin\n150 $ymax\n");
	GMT_setR($R);

	if (defined($opt_t)) {
		open(BT,$opt_t) || croak("$opt_t: $!\n");
		@BTL = &antsFileLayout(BT);
		my($BTwf,$BTdf,$BTmf,$BTnf);
		for (my($f)=0; $f<=$#BTL; $f++) {
			$BTdf = $f if ($BTL[$f] eq 'depth');
			$BTwf = $f if ($BTL[$f] eq 'BT_w');
			$BTmf = $f if ($BTL[$f] eq 'BT_w.mad');
			$BTnf = $f if ($BTL[$f] eq 'BT_w.nsamp');
		}
		croak("$opt_t: file-layout error\n")
			unless defined($BTdf) && defined($BTwf) &&
				   defined($BTmf) && defined($BTnf);
		GMT_psxy('-W6');
		while (@BT = &antsFileIn(BT)) {
			next unless numberp($BT[$BTwf]);
			printf(GMT "%f %f\n",$BT[$BTwf],$BT[$BTdf]);
		}
	}
}

$min_depth =  9e99;										# sentinels
$max_depth = -9e99;

$curF = '';												# current input file (sentinel)
$filt = 0;
for (my($curF),$r=0; &antsIn(); $r++) {
	if ($P{PATHNAME} ne $curF) {						# new file
		$curF = $P{PATHNAME};

		&antsInfo("WARNING: inconsistent %outgrid_dz in input files")
			if (defined($P{outgrid_dz}) && $P{outgrid_dz}!=$opt_o &&!$opt_o_override);
		&antsInfo("WARNING: inconsistent %outgrid_minsamp in input files")
			if (defined($P{outgrid_minsamp}) && $P{outgrid_minsamp}*2!=$opt_k &&!$opt_k_override);
		
		$bin_length = sprintf('%d & %d',round($bin_length),($P{ADCP_bin_length}))
			unless (round($bin_length) == round($P{ADCP_bin_length}));
		$pulse_length = sprintf('%d & %d',round($pulse_length),round($P{ADCP_pulse_length}))
			unless (round($pulse_length) == round($P{ADCP_pulse_length}));
		$blanking_dist = sprintf('%d & %d',round($blanking_dist),($P{ADCP_blanking_distance}))
			unless (round($blanking_dist) == round($P{ADCP_blanking_distance}));

		$PROF = $STN = $id; $RUN = antsRequireParam('run_label');
		undef(@dscMin); undef(@dscMax);
		do "./EditParams";

		if (@dcw1) {									# 2nd file in dual-head profile => plot 1st
			GMT_psxy('-W2,255/127/80,-');
			for (my($bi)=0; $bi<=$#dcw1; $bi++) {
				printf(GMT "%f %f\n",median(@{$dcw1[$bi]}),($bi+0.5)*$opt_o);
			}
			GMT_psxy('-W2,46/139/87,-');
			for (my($bi)=0; $bi<=$#ucw1; $bi++) {
				printf(GMT "%f %f\n",median(@{$ucw1[$bi]}),($bi+0.5)*$opt_o);
			}
			undef(@dcw1); undef(@ucw1);
		}
	}
	next if ($ants_[0][$bF]<$P{outgrid_firstbin}-1 || $ants_[0][$bF]>$P{outgrid_lastbin}-1);
	$filt++,next if &isBad();
	$min_depth = $ants_[0][$dF] if ($ants_[0][$dF] < $min_depth);
	$max_depth = $ants_[0][$dF] if ($ants_[0][$dF] > $max_depth);
	my($bi) = $ants_[0][$dF]/$opt_o;
	if ($ants_[0][$dcF]) {								# downcast
		push(@{$dcw[$bi]},$ants_[0][$wF]);				# vertical velocity
		push(@{$dcw1[$bi]},$ants_[0][$wF]) if ($dual_head);
		push(@{$dce[$bi]},$ants_[0][$eF]);	 			# elapsed time
	} else {								 			# upcast
		push(@{$ucw[$bi]},$ants_[0][$wF]);
		push(@{$ucw1[$bi]},$ants_[0][$wF]) if ($dual_head);
		push(@{$uce[$bi]},$ants_[0][$eF]);
	}
}

if (@dcw1) {											# 2nd file in dual-head profile in buffer => plot it
	GMT_psxy('-W2,255/127/80,.');
	for (my($bi)=0; $bi<=$#dcw1; $bi++) {
		printf(GMT "%f %f\n",median(@{$dcw1[$bi]}),($bi+0.5)*$opt_o);
	}
	GMT_psxy('-W2,46/139/87,.');
	for (my($bi)=0; $bi<=$#ucw1; $bi++) {
		printf(GMT "%f %f\n",median(@{$ucw1[$bi]}),($bi+0.5)*$opt_o);
	}
}

&antsInfo("%d measurements edited (%d%% of total)",$filt,round(100*$filt/$r))
	if ($filt > 0);

#----------------------------------------------------------------------
# Average and Output Profile, Add to Plot
#----------------------------------------------------------------------

@antsNewLayout = ('depth','hab',
				  'dc_elapsed','dc_w','dc_w.mad','dc_w.nsamp',
				  'uc_elapsed','uc_w','uc_w.mad','uc_w.nsamp');
				  		  
if ($dual_head) {										# selected %PARAMs only
	&antsAddParams('profile_id',$id,'lat',$P{lat},'lon',$P{lon});
	&antsAddParams($dayNoP,$dn,'run_label',"$first_label & $P{run_label}");
	&antsAddParams('outgrid_dz',$opt_o,'outgrid_minsamp',$opt_k);
	&antsAddParams('outgrid_firstbin',$P{outgrid_firstbin},'outgrid_lastbin',$P{outgrid_lastbin});
	&antsAddParams('ADCP_bin_length',round($bin_length),'ADCP_pulse_length',round($pulse_length))
	&antsAddParams('ADCP_blanking_distance',round($blanking_dist));
	&antsAddParams('min_depth',round($min_depth),'max_depth',round($max_depth));
	&antsAddParams('water_depth',$P{water_depth},'water_depth.sig',$P{water_depth.sig});
	undef($antsOldHeaders);
}

&antsInfo("WARNING: unknown water depth (no height-above-bottom)")
	unless numberp($P{water_depth});

my(@dcwm,@ucwm,@dcns,@ucns,@dcwmad,@ucwmad);
for (my($bi)=0; $bi<=max($#dcw,$#ucw); $bi++) {
	$dcwm[$bi] = median(@{$dcw[$bi]}); 
	$ucwm[$bi] = median(@{$ucw[$bi]});
	$dcns[$bi] = @{$dcw[$bi]};
	$ucns[$bi] = @{$ucw[$bi]};
	$dcwmad[$bi] = mad2($dcwm[$bi],@{$dcw[$bi]});
	$ucwmad[$bi] = mad2($ucwm[$bi],@{$ucw[$bi]});
	push(@{$out[$bi]},
			 ($bi+0.5)*$opt_o,
			 (numberp($P{water_depth}) ? $P{water_depth}-($bi+0.5)*$opt_o : nan),
			 avg(@{$dce[$bi]}),
			 (($dcns[$bi]>=$opt_k)?$dcwm[$bi]:nan),(($dcns[$bi]>=$opt_k)?$dcmad[$bi]:nan),
			 scalar(@{$dcw[$bi]}),
			 avg(@{$uce[$bi]}),
			 (($ucns[$bi]>=$opt_k)?$ucwm[$bi]:nan),(($ucns[$bi]>=$opt_k)?$ucmad[$bi]:nan),
			 scalar(@{$ucw[$bi]}));
	&antsOut(@{$out[$bi]});				 
}

if ($opt_p) {																		# complete plot
	GMT_setR($R);

	GMT_psxy('-W4,255/127/80');														# median profiles
	for (my($bi)=0; $bi<=$#dcw1; $bi++) {
		printf(GMT "%f %f\n",$dcwm[$bi],($bi+0.5)*$opt_o);
	}
	GMT_psxy('-W4,46/139/87');
	for (my($bi)=0; $bi<=$#ucw1; $bi++) {
		printf(GMT "%f %f\n",$ucwm[$bi],($bi+0.5)*$opt_o);
	}

	GMT_psxy('-Sc0.1 -G255/127/80');												# m.a.d. profiles
	for (my($bi)=0; $bi<=$#dcw1; $bi++) {
		printf(GMT "%f %f\n",$dcwmad[$bi],($bi+0.5)*$opt_o);
	}
	GMT_psxy('-Sc0.1 -G46/139/87');
	for (my($bi)=0; $bi<=$#ucw1; $bi++) {
		printf(GMT "%f %f\n",$ucwmad[$bi],($bi+0.5)*$opt_o);
	}

	GMT_setR($R2);
	GMT_psxy('-Mn -W1,255/127/80');
	for (my($bi)=0; $bi<=$#dcw1; $bi++) {
		printf(GMT "%f %f\n",$dcns[$bi],($bi+0.5)*$opt_o);
	}
	GMT_psxy('-Mn -W1,46/139/87');
	for (my($bi)=0; $bi<=$#dcw1; $bi++) {
		printf(GMT "%f %f\n",$ucns[$bi],($bi+0.5)*$opt_o);
	}

	GMT_psbasemap('-Bf10a1000-950:"                                     # of Samples":N');
	GMT_psbasemap('-Ba1000-900N'); GMT_psbasemap('-Ba1000-850N');

	$depth_tics = ($ymax-$ymin< 1000) ? 'f10a100' : 'f100a500';
	GMT_setR($R);
	GMT_psbasemap('-Bf0.01a10-10.05:"Vertical Velocity [m/s]                               ":/' .
						$depth_tics . ':"Depth [m]":WeS');
	GMT_psbasemap('-Ba10-9.95S'); GMT_psbasemap('-Ba10-9.85S');

	GMT_setR('-R0/1/0/1');
	GMT_pstext('-Gblue -N');
	if (defined($outfile)) { print(GMT "0.01 -0.06 14 0 0 TL $outfile\n"); }
	else { printf(GMT "0.01 -0.06 14 0 0 TL %03d\n",$id); }
	GMT_pstext();
	print(GMT '0.62 0.98 12 0 0 MR m.a.d.');
	GMT_end();
}

&antsExit(0);